diff options
Diffstat (limited to 'src/proguard')
652 files changed, 15486 insertions, 3876 deletions
diff --git a/src/proguard/ArgumentWordReader.java b/src/proguard/ArgumentWordReader.java index efe8e6e..3d04af3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/AssumeNoSideEffectsChecker.java b/src/proguard/AssumeNoSideEffectsChecker.java new file mode 100644 index 0000000..5932b70 --- /dev/null +++ b/src/proguard/AssumeNoSideEffectsChecker.java @@ -0,0 +1,98 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 java.util.List; + +/** + * This class checks if the user is specifying to assume no side effects + * for a reasonable number of methods in a class: not none and not all. + * + * @author Eric Lafortune + */ +public class AssumeNoSideEffectsChecker +{ + private final WarningPrinter notePrinter; + + + /** + * Creates a new KeepClassMemberChecker. + */ + public AssumeNoSideEffectsChecker(WarningPrinter notePrinter) + { + this.notePrinter = notePrinter; + } + + + /** + * Checks if the given class specifications try to assume no side effects + * for all methods in a class, printing notes if necessary. + */ + public void checkClassSpecifications(List classSpecifications) + { + if (classSpecifications != null) + { + for (int classSpecificationIndex = 0; + classSpecificationIndex < classSpecifications.size(); + classSpecificationIndex++) + { + ClassSpecification classSpecification = + (ClassSpecification)classSpecifications.get(classSpecificationIndex); + + String className = classSpecification.className; + if (className == null) + { + className = classSpecification.extendsClassName; + } + + if (className == null || + notePrinter.accepts(className)) + { + List methodSpecifications = + classSpecification.methodSpecifications; + + if (methodSpecifications != null) + { + for (int methodSpecificationIndex = 0; + methodSpecificationIndex < methodSpecifications.size(); + methodSpecificationIndex++) + { + final MemberSpecification methodSpecification = + (MemberSpecification)methodSpecifications.get(methodSpecificationIndex); + + if (methodSpecification.name == null && + methodSpecification.descriptor == null) + { + notePrinter.print(className, + "Note: the configuration specifies that none of the methods of class '" + + (className == null ? + ConfigurationConstants.ANY_CLASS_KEYWORD : + ClassUtil.externalClassName(className)) + "' have any side effects"); + } + } + } + } + } + } + } +} diff --git a/src/proguard/ClassMemberChecker.java b/src/proguard/ClassMemberChecker.java new file mode 100644 index 0000000..249105e --- /dev/null +++ b/src/proguard/ClassMemberChecker.java @@ -0,0 +1,158 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.*; +import proguard.classfile.util.*; +import proguard.classfile.visitor.MemberVisitor; + +import java.util.List; + +/** + * This class checks if the user has specified non-existent class members. + * + * @author Eric Lafortune + */ +public class ClassMemberChecker +extends SimplifiedVisitor +implements MemberVisitor +{ + private final ClassPool programClassPool; + private final WarningPrinter notePrinter; + + + /** + * Creates a new ClassMemberChecker. + */ + public ClassMemberChecker(ClassPool programClassPool, + WarningPrinter notePrinter) + { + this.programClassPool = programClassPool; + this.notePrinter = notePrinter; + } + + + /** + * Checks the classes mentioned in the given class specifications, printing + * notes if necessary. + */ + public void checkClassSpecifications(List classSpecifications) + { + if (classSpecifications != null) + { + for (int index = 0; index < classSpecifications.size(); index++) + { + ClassSpecification classSpecification = + (ClassSpecification)classSpecifications.get(index); + + String className = classSpecification.className; + if (className != null && + !containsWildCards(className) && + notePrinter.accepts(className)) + { + Clazz clazz = programClassPool.getClass(className); + if (clazz != null) + { + checkMemberSpecifications(clazz, classSpecification.fieldSpecifications, true); + checkMemberSpecifications(clazz, classSpecification.methodSpecifications, false); + } + } + } + } + } + + + /** + * Checks the class members mentioned in the given class member + * specifications, printing notes if necessary. + */ + private void checkMemberSpecifications(Clazz clazz, + List memberSpecifications, + boolean isField) + { + if (memberSpecifications != null) + { + String className = clazz.getName(); + + for (int index = 0; index < memberSpecifications.size(); index++) + { + MemberSpecification memberSpecification = + (MemberSpecification)memberSpecifications.get(index); + + String memberName = memberSpecification.name; + String descriptor = memberSpecification.descriptor; + if (memberName != null && + !containsWildCards(memberName) && + descriptor != null && + !containsWildCards(descriptor)) + { + if (isField) + { + if (clazz.findField(memberName, descriptor) == null) + { + notePrinter.print(className, + "Note: the configuration refers to the unknown field '" + + ClassUtil.externalFullFieldDescription(0, memberName, descriptor) + "' in class '" + + ClassUtil.externalClassName(className) + "'"); + } + } + else + { + if (clazz.findMethod(memberName, descriptor) == null) + { + notePrinter.print(className, + "Note: the configuration refers to the unknown method '" + + ClassUtil.externalFullMethodDescription(className, 0, memberName, descriptor) + "' in class '" + + ClassUtil.externalClassName(className) + "'"); + } + } + } + } + } + } + + + private static boolean containsWildCards(String string) + { + return string != null && + (string.indexOf('!') >= 0 || + string.indexOf('*') >= 0 || + string.indexOf('?') >= 0 || + string.indexOf(',') >= 0 || + string.indexOf("///") >= 0); + } + + + // Implementations for MemberVisitor. + + public void visitProgramField(ProgramClass programClass, ProgramField programField) + { + System.out.println(" Maybe you meant the field '" + + ClassUtil.externalFullFieldDescription(0, programField.getName(programClass), programField.getDescriptor(programClass)) + "'?"); + } + + + public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) + { + System.out.println(" Maybe you meant the method '" + + ClassUtil.externalFullMethodDescription(programClass.getName(), 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) + "'?"); + } +}
\ No newline at end of file diff --git a/src/proguard/ClassPath.java b/src/proguard/ClassPath.java index 3d7d119..092a78d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 7051955..faceb1f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,11 @@ import java.util.List; /** - * This class represents an entry from a class path: a jar, a war, a zip, an - * ear, or a directory, with a name and a flag to indicates whether the entry is - * an input entry or an output entry. Optional filters can be specified for the - * names of the contained resource/classes, jars, wars, ears, and zips. + * This class represents an entry from a class path: an apk, a jar, an aar, a + * war, a zip, an ear, or a directory, with a name and a flag to indicates + * whether the entry is an input entry or an output entry. Optional filters can + * be specified for the names of the contained resource/classes, apks, jars, + * aars, wars, ears, and zips. * * @author Eric Lafortune */ @@ -39,11 +40,15 @@ public class ClassPathEntry private File file; private boolean output; private List filter; + private List apkFilter; private List jarFilter; + private List aarFilter; private List warFilter; private List earFilter; private List zipFilter; + private String cachedName; + /** * Creates a new ClassPathEntry with the given file and output flag. @@ -60,6 +65,20 @@ public class ClassPathEntry */ public String getName() { + if (cachedName == null) + { + cachedName = getUncachedName(); + } + + return cachedName; + } + + + /** + * Returns the uncached path name of the entry. + */ + private String getUncachedName() + { try { return file.getCanonicalPath(); @@ -85,7 +104,8 @@ public class ClassPathEntry */ public void setFile(File file) { - this.file = file; + this.file = file; + this.cachedName = null; } @@ -108,6 +128,25 @@ public class ClassPathEntry /** + * Returns whether this data entry is a dex file. + */ + public boolean isDex() + { + return hasExtension(".dex"); + } + + + /** + * Returns whether this data entry is an apk file. + */ + public boolean isApk() + { + return hasExtension(".apk") || + hasExtension(".ap_"); + } + + + /** * Returns whether this data entry is a jar file. */ public boolean isJar() @@ -117,6 +156,15 @@ public class ClassPathEntry /** + * Returns whether this data entry is an aar file. + */ + public boolean isAar() + { + return hasExtension(".aar"); + } + + + /** * Returns whether this data entry is a war file. */ public boolean isWar() @@ -167,6 +215,21 @@ public class ClassPathEntry /** + * Returns whether this data entry has any kind of filter. + */ + public boolean isFiltered() + { + return filter != null || + apkFilter != null || + jarFilter != null || + aarFilter != null || + warFilter != null || + earFilter != null || + zipFilter != null; + } + + + /** * Returns the name filter that is applied to bottom-level files in this entry. */ public List getFilter() @@ -184,6 +247,23 @@ public class ClassPathEntry /** + * Returns the name filter that is applied to apk files in this entry, if any. + */ + public List getApkFilter() + { + return apkFilter; + } + + /** + * Sets the name filter that is applied to apk files in this entry, if any. + */ + public void setApkFilter(List filter) + { + this.apkFilter = 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() @@ -201,6 +281,23 @@ public class ClassPathEntry /** + * Returns the name filter that is applied to aar files in this entry, if any. + */ + public List getAarFilter() + { + return aarFilter; + } + + /** + * Sets the name filter that is applied to aar files in this entry, if any. + */ + public void setAarFilter(List filter) + { + this.aarFilter = 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() @@ -259,12 +356,17 @@ public class ClassPathEntry if (filter != null || jarFilter != null || + aarFilter != null || warFilter != null || earFilter != null || zipFilter != null) { string += ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD + + (aarFilter != null ? ListUtil.commaSeparatedString(aarFilter, true) : "") + + ConfigurationConstants.SEPARATOR_KEYWORD + + (apkFilter != null ? ListUtil.commaSeparatedString(apkFilter, true) : "") + + ConfigurationConstants.SEPARATOR_KEYWORD + (zipFilter != null ? ListUtil.commaSeparatedString(zipFilter, true) : "") + ConfigurationConstants.SEPARATOR_KEYWORD + (earFilter != null ? ListUtil.commaSeparatedString(earFilter, true) : "") + diff --git a/src/proguard/ClassSpecification.java b/src/proguard/ClassSpecification.java index 485c0b0..c2b6bfd 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 dc5d71f..b403dde 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,12 +39,18 @@ public class ClassSpecificationVisitorFactory * classes and class members. * * @param keepClassSpecifications the list of KeepClassSpecification - * instances, defining of the classes and + * instances that specify the classes and * class members to visit. * @param classVisitor the ClassVisitor to be applied to matching * classes. * @param memberVisitor the MemberVisitor to be applied to matching * class members. + * @param shrinking a flag that specifies whether the visitors + * are intended for the shrinking step. + * @param optimizing a flag that specifies whether the visitors + * are intended for the optimization step. + * @param obfuscating a flag that specifies whether the visitors + * are intended for the obfuscation step. */ public static ClassPoolVisitor createClassPoolVisitor(List keepClassSpecifications, ClassVisitor classVisitor, @@ -82,9 +88,9 @@ public class ClassSpecificationVisitorFactory * Constructs a ClassPoolVisitor to efficiently travel to the specified * classes and class members. * - * @param classSpecifications the list of ClassSpecification instances, - * defining of the classes and class members to - * visit. + * @param classSpecifications the list of ClassSpecification instances + * that specify the classes and class members + * to visit. * @param classVisitor the ClassVisitor to be applied to matching * classes. * @param memberVisitor the MemberVisitor to be applied to matching @@ -118,17 +124,31 @@ public class ClassSpecificationVisitorFactory * Constructs a ClassPoolVisitor to efficiently travel to the specified * classes and class members. * - * @param keepClassSpecification the specifications of the class(es) and class - * members to visit. - * @param classVisitor the ClassVisitor to be applied to matching - * classes. - * @param memberVisitor the MemberVisitor to be applied to matching - * class members. + * @param keepClassSpecification the specifications of the class(es) and + * class members to visit. + * @param classVisitor the ClassVisitor to be applied to + * matching classes. + * @param memberVisitor the MemberVisitor to be applied to + * matching class members. */ - private static ClassPoolVisitor createClassPoolVisitor(KeepClassSpecification keepClassSpecification, - ClassVisitor classVisitor, - MemberVisitor memberVisitor) + public static ClassPoolVisitor createClassPoolVisitor(KeepClassSpecification keepClassSpecification, + ClassVisitor classVisitor, + MemberVisitor memberVisitor) { + // If specified, let the class visitor also visit the descriptor + // classes. + if (keepClassSpecification.markDescriptorClasses && + classVisitor != null) + { + memberVisitor = memberVisitor == null ? + new MemberDescriptorReferencedClassVisitor(classVisitor) : + new MultiMemberVisitor(new MemberVisitor[] + { + memberVisitor, + new MemberDescriptorReferencedClassVisitor(classVisitor) + }); + } + // Don't visit the classes if not specified. if (!keepClassSpecification.markClasses && !keepClassSpecification.markConditionally) @@ -172,9 +192,9 @@ public class ClassSpecificationVisitorFactory * @param memberVisitor the MemberVisitor to be applied to matching * class members. */ - private static ClassPoolVisitor createClassPoolVisitor(ClassSpecification classSpecification, - ClassVisitor classVisitor, - MemberVisitor memberVisitor) + public static ClassPoolVisitor createClassPoolVisitor(ClassSpecification classSpecification, + ClassVisitor classVisitor, + MemberVisitor memberVisitor) { // Combine both visitors. ClassVisitor composedClassVisitor = diff --git a/src/proguard/Configuration.java b/src/proguard/Configuration.java index 4711260..0b855a5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/ConfigurationChecker.java b/src/proguard/ConfigurationChecker.java new file mode 100644 index 0000000..84d4663 --- /dev/null +++ b/src/proguard/ConfigurationChecker.java @@ -0,0 +1,224 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.WarningPrinter; + +import java.io.IOException; + +/** + * This class performs sanity checks on a given configurations. + * + * @author Eric Lafortune + */ +public class ConfigurationChecker +{ + private final Configuration configuration; + + + /** + * Creates a new ConfigurationChecker with the given configuration. + */ + public ConfigurationChecker(Configuration configuration) + { + this.configuration = configuration; + } + + + /** + * Checks the given configuration for potential problems. + */ + public void check() throws IOException + { + ClassPath programJars = configuration.programJars; + ClassPath libraryJars = configuration.libraryJars; + + // Check that the input isn't empty. + if (programJars == null) + { + throw new IOException("The input is empty. You have to specify one or more '-injars' options."); + } + + // Check that the first jar is an input jar. + ClassPathEntry firstEntry = programJars.get(0); + if (firstEntry.isOutput()) + { + throw new IOException("The output jar [" + firstEntry.getName() + + "] must be specified after an input jar, or it will be empty."); + } + + // Check that 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() && + !entry.isFiltered() && + programJars.get(index + 1).isOutput()) + { + throw new IOException("The output jar [" + entry.getName() + + "] must have a filter, or all subsequent output jars will be empty."); + } + } + + // Check for conflicts between input/output entries of the class paths. + checkConflicts(programJars, programJars); + checkConflicts(programJars, libraryJars); + checkConflicts(libraryJars, libraryJars); + + // Print out some general notes if necessary. + if ((configuration.note == null || + !configuration.note.isEmpty())) + { + // Check for potential problems with mixed-case class names on + // case-insensitive file systems. + if (configuration.obfuscate && + configuration.useMixedCaseClassNames && + configuration.classObfuscationDictionary == null) + { + 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.isApk() && + !entry.isJar() && + !entry.isAar() && + !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; + } + } + } + } + + // Check if -adaptresourcefilecontents has a proper filter. + if (configuration.adaptResourceFileContents != null && + (configuration.adaptResourceFileContents.isEmpty() || + configuration.adaptResourceFileContents.get(0).equals(ConfigurationConstants.ANY_FILE_KEYWORD))) + { + System.out.println("Note: you're specifying '-adaptresourcefilecontents' for all resource files."); + System.out.println(" This will most likely cause problems with binary files."); + } + + // Check if all -keepclassmembers options indeed have class members. + WarningPrinter keepClassMemberNotePrinter = new WarningPrinter(System.out, configuration.note); + + new KeepClassMemberChecker(keepClassMemberNotePrinter).checkClassSpecifications(configuration.keep); + + // Check if -assumenosideffects options don't specify all methods. + WarningPrinter assumeNoSideEffectsNotePrinter = new WarningPrinter(System.out, configuration.note); + + new AssumeNoSideEffectsChecker(assumeNoSideEffectsNotePrinter).checkClassSpecifications(configuration.assumeNoSideEffects); + + // 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 assumeNoSideEffectsNoteCount = assumeNoSideEffectsNotePrinter.getWarningCount(); + if (assumeNoSideEffectsNoteCount > 0) + { + System.out.println("Note: there were " + assumeNoSideEffectsNoteCount + + " '-assumenosideeffects' options that try to match all"); + System.out.println(" methods with wildcards. This will likely cause problems with methods like"); + System.out.println(" 'wait()' and 'notify()'. You should specify the methods more precisely."); + System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#nosideeffects)"); + } + } + } + + + /** + * Performs some sanity checks on the class paths. + */ + private void checkConflicts(ClassPath classPath1, + ClassPath classPath2) + throws IOException + { + if (classPath1 == null || + classPath2 == null) + { + return; + } + + for (int index1 = 0; index1 < classPath1.size(); index1++) + { + ClassPathEntry entry1 = classPath1.get(index1); + + for (int index2 = 0; index2 < classPath2.size(); index2++) + { + if (classPath1 != classPath2 || index1 != index2) + { + ClassPathEntry entry2 = classPath2.get(index2); + + if (entry2.getName().equals(entry1.getName())) + { + if (entry1.isOutput()) + { + if (entry2.isOutput()) + { + // Output / output. + throw new IOException("The same output jar ["+entry1.getName()+"] is specified twice."); + } + else + { + // Output / input. + throw new IOException("Input jars and output jars must be different ["+entry1.getName()+"]."); + } + } + else + { + if (entry2.isOutput()) + { + // Input / output. + throw new IOException("Input jars and output jars must be different ["+entry1.getName()+"]."); + } + else if (!entry1.isFiltered() || + !entry2.isFiltered()) + { + // Input / input. + throw new IOException("The same input jar ["+entry1.getName()+"] is specified twice."); + } + } + } + } + } + } + } +} diff --git a/src/proguard/ConfigurationConstants.java b/src/proguard/ConfigurationConstants.java index 14c5654..a67eee3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 @@ class ConfigurationConstants public static final String KEEP_NAMES_OPTION = "-keepnames"; public static final String KEEP_CLASS_MEMBER_NAMES_OPTION = "-keepclassmembernames"; public static final String KEEP_CLASSES_WITH_MEMBER_NAMES_OPTION = "-keepclasseswithmembernames"; + public static final String INCLUDE_DESCRIPTOR_CLASSES_SUBOPTION = "includedescriptorclasses"; public static final String ALLOW_SHRINKING_SUBOPTION = "allowshrinking"; public static final String ALLOW_OPTIMIZATION_SUBOPTION = "allowoptimization"; public static final String ALLOW_OBFUSCATION_SUBOPTION = "allowobfuscation"; @@ -95,6 +96,8 @@ class ConfigurationConstants public static final String KEEP_DIRECTORIES_OPTION = "-keepdirectories"; public static final String FORCE_PROCESSING_OPTION = "-forceprocessing"; + public static final String ANY_FILE_KEYWORD = "**"; + public static final String ANY_ATTRIBUTE_KEYWORD = "*"; public static final String ATTRIBUTE_SEPARATOR_KEYWORD = ","; diff --git a/src/proguard/ConfigurationParser.java b/src/proguard/ConfigurationParser.java index a38e9ed..72949cf 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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; -import proguard.classfile.ClassConstants; +import proguard.classfile.*; import proguard.classfile.util.ClassUtil; import proguard.util.ListUtil; @@ -236,7 +236,7 @@ public class ConfigurationParser private long parseIncludeArgument(long lastModified) throws ParseException, IOException { - // Read the configuation file name. + // Read the configuration file name. readNextWord("configuration file name", true, false); File file = file(nextWord); @@ -285,7 +285,7 @@ public class ConfigurationParser ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD.equals(nextWord)) { // Read all filters in an array. - List[] filters = new List[5]; + List[] filters = new List[7]; int counter = 0; do @@ -320,6 +320,18 @@ public class ConfigurationParser if (counter > 0) { entry.setZipFilter(filters[--counter]); + if (counter > 0) + { + // For backward compatibility, the apk + // filter comes second in the list. + entry.setApkFilter(filters[--counter]); + if (counter > 0) + { + // For backward compatibility, the aar + // filter comes first in the list. + entry.setAarFilter(filters[--counter]); + } + } } } } @@ -469,16 +481,17 @@ public class ConfigurationParser keepClassSpecifications = new ArrayList(); } - //boolean allowShrinking = false; - boolean allowOptimization = false; - boolean allowObfuscation = false; + boolean markDescriptorClasses = false; + //boolean allowShrinking = false; + boolean allowOptimization = false; + boolean allowObfuscation = false; // Read the keep modifiers. while (true) { readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD + - "', '" + ClassConstants.EXTERNAL_ACC_INTERFACE + - "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", + "', '" + JavaConstants.ACC_INTERFACE + + "', or '" + JavaConstants.ACC_ENUM + "'", false, true); if (!ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD.equals(nextWord)) @@ -491,21 +504,26 @@ public class ConfigurationParser "', '" + ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION + "', or '" + ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION + "'"); - if (ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION .startsWith(nextWord)) + if (ConfigurationConstants.INCLUDE_DESCRIPTOR_CLASSES_SUBOPTION.startsWith(nextWord)) { - allowShrinking = true; + markDescriptorClasses = true; } - else if (ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION.startsWith(nextWord)) + else if (ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION .startsWith(nextWord)) { - allowOptimization = true; + allowShrinking = true; } - else if (ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION .startsWith(nextWord)) + else if (ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION .startsWith(nextWord)) { - allowObfuscation = true; + allowOptimization = true; + } + else if (ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION .startsWith(nextWord)) + { + allowObfuscation = true; } else { - throw new ParseException("Expecting keyword '" + ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION + + throw new ParseException("Expecting keyword '" + ConfigurationConstants.INCLUDE_DESCRIPTOR_CLASSES_SUBOPTION + + "', '" + ConfigurationConstants.ALLOW_SHRINKING_SUBOPTION + "', '" + ConfigurationConstants.ALLOW_OPTIMIZATION_SUBOPTION + "', or '" + ConfigurationConstants.ALLOW_OBFUSCATION_SUBOPTION + "' before " + reader.locationDescription()); @@ -519,6 +537,7 @@ public class ConfigurationParser // Create and add the keep configuration. keepClassSpecifications.add(new KeepClassSpecification(markClasses, markConditionally, + markDescriptorClasses, allowShrinking, allowOptimization, allowObfuscation, @@ -538,8 +557,8 @@ public class ConfigurationParser // Read and add the class configuration. readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD + - "', '" + ClassConstants.EXTERNAL_ACC_INTERFACE + - "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", + "', '" + JavaConstants.ACC_INTERFACE + + "', or '" + JavaConstants.ACC_ENUM + "'", false, true); classSpecifications.add(parseClassSpecificationArguments()); @@ -577,25 +596,25 @@ public class ConfigurationParser // Parse the class access modifiers. 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(); + strippedWord.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC : + strippedWord.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL : + strippedWord.equals(JavaConstants.ACC_INTERFACE) ? ClassConstants.ACC_INTERFACE : + strippedWord.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT : + strippedWord.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC : + strippedWord.equals(JavaConstants.ACC_ANNOTATION) ? ClassConstants.ACC_ANNOTATTION : + strippedWord.equals(JavaConstants.ACC_ENUM) ? ClassConstants.ACC_ENUM : + unknownAccessFlag(); // Is it an annotation modifier? - if (accessFlag == ClassConstants.INTERNAL_ACC_ANNOTATTION) + if (accessFlag == ClassConstants.ACC_ANNOTATTION) { // Already read the next word. - readNextWord("annotation type or keyword '" + ClassConstants.EXTERNAL_ACC_INTERFACE + "'", + readNextWord("annotation type or keyword '" + JavaConstants.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) && + if (!nextWord.equals(JavaConstants.ACC_INTERFACE) && + !nextWord.equals(JavaConstants.ACC_ENUM) && !nextWord.equals(ConfigurationConstants.CLASS_KEYWORD)) { // Parse the annotation type. @@ -628,8 +647,8 @@ public class ConfigurationParser "' before " + reader.locationDescription()); } - if (strippedWord.equals(ClassConstants.EXTERNAL_ACC_INTERFACE) || - strippedWord.equals(ClassConstants.EXTERNAL_ACC_ENUM) || + if (strippedWord.equals(JavaConstants.ACC_INTERFACE) || + strippedWord.equals(JavaConstants.ACC_ENUM) || strippedWord.equals(ConfigurationConstants.CLASS_KEYWORD)) { // The interface or enum keyword. Stop parsing the class flags. @@ -637,11 +656,11 @@ public class ConfigurationParser } // Should we read the next word? - if (accessFlag != ClassConstants.INTERNAL_ACC_ANNOTATTION) + if (accessFlag != ClassConstants.ACC_ANNOTATTION) { readNextWord("keyword '" + ConfigurationConstants.CLASS_KEYWORD + - "', '" + ClassConstants.EXTERNAL_ACC_INTERFACE + - "', or '" + ClassConstants.EXTERNAL_ACC_ENUM + "'", + "', '" + JavaConstants.ACC_INTERFACE + + "', or '" + JavaConstants.ACC_ENUM + "'", false, true); } } @@ -764,21 +783,21 @@ public class ConfigurationParser // Parse the class member access modifiers. int accessFlag = - strippedWord.equals(ClassConstants.EXTERNAL_ACC_PUBLIC) ? ClassConstants.INTERNAL_ACC_PUBLIC : - strippedWord.equals(ClassConstants.EXTERNAL_ACC_PRIVATE) ? ClassConstants.INTERNAL_ACC_PRIVATE : - strippedWord.equals(ClassConstants.EXTERNAL_ACC_PROTECTED) ? ClassConstants.INTERNAL_ACC_PROTECTED : - strippedWord.equals(ClassConstants.EXTERNAL_ACC_STATIC) ? ClassConstants.INTERNAL_ACC_STATIC : - strippedWord.equals(ClassConstants.EXTERNAL_ACC_FINAL) ? ClassConstants.INTERNAL_ACC_FINAL : - 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; + strippedWord.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC : + strippedWord.equals(JavaConstants.ACC_PRIVATE) ? ClassConstants.ACC_PRIVATE : + strippedWord.equals(JavaConstants.ACC_PROTECTED) ? ClassConstants.ACC_PROTECTED : + strippedWord.equals(JavaConstants.ACC_STATIC) ? ClassConstants.ACC_STATIC : + strippedWord.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL : + strippedWord.equals(JavaConstants.ACC_SYNCHRONIZED) ? ClassConstants.ACC_SYNCHRONIZED : + strippedWord.equals(JavaConstants.ACC_VOLATILE) ? ClassConstants.ACC_VOLATILE : + strippedWord.equals(JavaConstants.ACC_TRANSIENT) ? ClassConstants.ACC_TRANSIENT : + strippedWord.equals(JavaConstants.ACC_BRIDGE) ? ClassConstants.ACC_BRIDGE : + strippedWord.equals(JavaConstants.ACC_VARARGS) ? ClassConstants.ACC_VARARGS : + strippedWord.equals(JavaConstants.ACC_NATIVE) ? ClassConstants.ACC_NATIVE : + strippedWord.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT : + strippedWord.equals(JavaConstants.ACC_STRICT) ? ClassConstants.ACC_STRICT : + strippedWord.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC : + 0; if (accessFlag == 0) { // Not a class member access modifier. Stop parsing them. @@ -882,7 +901,7 @@ public class ConfigurationParser { // This must be a constructor then. // Make sure the type is a proper constructor name. - if (!(type.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) || + if (!(type.equals(ClassConstants.METHOD_NAME_INIT) || type.equals(externalClassName) || type.equals(ClassUtil.externalShortClassName(externalClassName)))) { @@ -892,8 +911,8 @@ public class ConfigurationParser } // Assign the fixed constructor type and name. - type = ClassConstants.EXTERNAL_TYPE_VOID; - name = ClassConstants.INTERNAL_METHOD_NAME_INIT; + type = JavaConstants.TYPE_VOID; + name = ClassConstants.METHOD_NAME_INIT; } else { @@ -974,22 +993,22 @@ public class ConfigurationParser /** * 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, ...) + * ("directory name", true, true, false, true, false, true, false, false, ...) + * ("optimization", true, false, false, false, false, false, false, false, ...) + * ("package name", true, true, false, false, true, false, true, false, ...) + * ("attribute name", true, true, false, false, true, false, false, false, ...) + * ("class name", true, true, false, false, true, false, true, false, ...) + * ("resource file", true, true, false, true, false, false, false, false, ...) + * ("resource file", 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, @@ -1141,9 +1160,7 @@ public class ConfigurationParser int toIndex = word.indexOf(ConfigurationConstants.CLOSE_SYSTEM_PROPERTY, fromIndex+1); if (toIndex < 0) { - throw new ParseException("Expecting closing '" + ConfigurationConstants.CLOSE_SYSTEM_PROPERTY + - "' after opening '" + ConfigurationConstants.OPEN_SYSTEM_PROPERTY + - "' in " + reader.locationDescription()); + break; } String propertyName = word.substring(fromIndex+1, toIndex); @@ -1154,9 +1171,9 @@ public class ConfigurationParser "' is undefined in " + reader.locationDescription()); } - word = word.substring(0, fromIndex) + - propertyValue + - word.substring(toIndex+1); + word = word.substring(0, fromIndex) + propertyValue + word.substring(toIndex+1); + + fromIndex += propertyValue.length(); } return word; @@ -1290,7 +1307,7 @@ public class ConfigurationParser { if (((requiredSetMemberAccessFlags | requiredUnsetMemberAccessFlags) & - ~ClassConstants.VALID_INTERNAL_ACC_FIELD) != 0) + ~ClassConstants.VALID_ACC_FIELD) != 0) { throw new ParseException("Invalid method access modifier for field before " + reader.locationDescription()); @@ -1308,7 +1325,7 @@ public class ConfigurationParser { if (((requiredSetMemberAccessFlags | requiredUnsetMemberAccessFlags) & - ~ClassConstants.VALID_INTERNAL_ACC_METHOD) != 0) + ~ClassConstants.VALID_ACC_METHOD) != 0) { throw new ParseException("Invalid field access modifier for method before " + reader.locationDescription()); diff --git a/src/proguard/ConfigurationWriter.java b/src/proguard/ConfigurationWriter.java index 00dfa9e..d87f47e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -188,6 +188,10 @@ public class ConfigurationWriter // Append the filters, if any. boolean filtered = false; + // For backward compatibility, the aar and apk filters come + // first. + filtered = writeFilter(filtered, entry.getAarFilter()); + filtered = writeFilter(filtered, entry.getApkFilter()); filtered = writeFilter(filtered, entry.getZipFilter()); filtered = writeFilter(filtered, entry.getEarFilter()); filtered = writeFilter(filtered, entry.getWarFilter()); @@ -340,7 +344,13 @@ public class ConfigurationWriter // Compose the option name. String optionName = optionNames[keepClassSpecification.markConditionally ? 2 : keepClassSpecification.markClasses ? 0 : - 1]; + 1]; + + if (keepClassSpecification.markDescriptorClasses) + { + optionName += ConfigurationConstants.ARGUMENT_SEPARATOR_KEYWORD + + ConfigurationConstants.INCLUDE_DESCRIPTOR_CLASSES_SUBOPTION; + } if (keepClassSpecification.allowShrinking) { @@ -407,8 +417,8 @@ public class ConfigurationWriter // keyword earlier. if (((classSpecification.requiredSetAccessFlags | classSpecification.requiredUnsetAccessFlags) & - (ClassConstants.INTERNAL_ACC_INTERFACE | - ClassConstants.INTERNAL_ACC_ENUM)) == 0) + (ClassConstants.ACC_INTERFACE | + ClassConstants.ACC_ENUM)) == 0) { writer.print(ConfigurationConstants.CLASS_KEYWORD); } @@ -564,7 +574,7 @@ public class ConfigurationWriter writer.print(descriptor == null ? name == null ? ConfigurationConstants.ANY_METHOD_KEYWORD : ConfigurationConstants.ANY_TYPE_KEYWORD + ' ' + name + ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD + ConfigurationConstants.ANY_ARGUMENTS_KEYWORD + ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD : - ClassUtil.externalFullMethodDescription(ClassConstants.INTERNAL_METHOD_NAME_INIT, + ClassUtil.externalFullMethodDescription(ClassConstants.METHOD_NAME_INIT, 0, name == null ? ConfigurationConstants.ANY_CLASS_MEMBER_KEYWORD : name, descriptor)); diff --git a/src/proguard/DataEntryReaderFactory.java b/src/proguard/DataEntryReaderFactory.java index 3bf6f56..57f3faa 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,26 +48,34 @@ public class DataEntryReaderFactory ClassPathEntry classPathEntry, DataEntryReader reader) { + boolean isApk = classPathEntry.isApk(); boolean isJar = classPathEntry.isJar(); + boolean isAar = classPathEntry.isAar(); boolean isWar = classPathEntry.isWar(); boolean isEar = classPathEntry.isEar(); boolean isZip = classPathEntry.isZip(); List filter = classPathEntry.getFilter(); + List apkFilter = classPathEntry.getApkFilter(); List jarFilter = classPathEntry.getJarFilter(); + List aarFilter = classPathEntry.getAarFilter(); List warFilter = classPathEntry.getWarFilter(); List earFilter = classPathEntry.getEarFilter(); List zipFilter = classPathEntry.getZipFilter(); System.out.println(messagePrefix + - (isJar ? "jar" : + (isApk ? "apk" : + isJar ? "jar" : + isAar ? "aar" : isWar ? "war" : isEar ? "ear" : isZip ? "zip" : "directory") + " [" + classPathEntry.getName() + "]" + (filter != null || + apkFilter != null || jarFilter != null || + aarFilter != null || warFilter != null || earFilter != null || zipFilter != null ? " (filtered)" : "")); @@ -81,20 +89,30 @@ public class DataEntryReaderFactory reader); } - // Unzip any jars, if necessary. - reader = wrapInJarReader(reader, isJar, jarFilter, ".jar"); - if (!isJar) + // Unzip any apks, if necessary. + reader = wrapInJarReader(reader, isApk, apkFilter, ".apk"); + if (!isApk) { - // Unzip any wars, if necessary. - reader = wrapInJarReader(reader, isWar, warFilter, ".war"); - if (!isWar) + // Unzip any jars, if necessary. + reader = wrapInJarReader(reader, isJar, jarFilter, ".jar"); + if (!isJar) { - // Unzip any ears, if necessary. - reader = wrapInJarReader(reader, isEar, earFilter, ".ear"); - if (!isEar) + // Unzip any aars, if necessary. + reader = wrapInJarReader(reader, isAar, aarFilter, ".aar"); + if (!isAar) { - // Unzip any zips, if necessary. - reader = wrapInJarReader(reader, isZip, zipFilter, ".zip"); + // Unzip any wars, if necessary. + reader = wrapInJarReader(reader, isWar, warFilter, ".war"); + if (!isWar) + { + // Unzip any ears, if necessary. + reader = wrapInJarReader(reader, isEar, earFilter, ".ear"); + if (!isEar) + { + // Unzip any zips, if necessary. + reader = wrapInJarReader(reader, isZip, zipFilter, ".zip"); + } + } } } } diff --git a/src/proguard/DataEntryWriterFactory.java b/src/proguard/DataEntryWriterFactory.java index ca33a35..d76e596 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 java.util.List; /** * This class can create DataEntryWriter instances based on class paths. The - * writers will wrap the output in the proper jars, wars, ears, and zips. + * writers will wrap the output in the proper apks, jars, wars, ears, and zips. * * @author Eric Lafortune */ @@ -65,41 +65,53 @@ public class DataEntryWriterFactory private static DataEntryWriter createClassPathEntryWriter(ClassPathEntry classPathEntry, DataEntryWriter alternativeWriter) { + boolean isApk = classPathEntry.isApk(); boolean isJar = classPathEntry.isJar(); + boolean isAar = classPathEntry.isAar(); boolean isWar = classPathEntry.isWar(); boolean isEar = classPathEntry.isEar(); boolean isZip = classPathEntry.isZip(); List filter = classPathEntry.getFilter(); + List apkFilter = classPathEntry.getApkFilter(); List jarFilter = classPathEntry.getJarFilter(); + List aarFilter = classPathEntry.getAarFilter(); List warFilter = classPathEntry.getWarFilter(); List earFilter = classPathEntry.getEarFilter(); List zipFilter = classPathEntry.getZipFilter(); System.out.println("Preparing output " + - (isJar ? "jar" : + (isApk ? "apk" : + isJar ? "jar" : + isAar ? "aar" : isWar ? "war" : isEar ? "ear" : isZip ? "zip" : "directory") + " [" + classPathEntry.getName() + "]" + (filter != null || + apkFilter != null || jarFilter != null || + aarFilter != null || warFilter != null || earFilter != null || zipFilter != null ? " (filtered)" : "")); DataEntryWriter writer = new DirectoryWriter(classPathEntry.getFile(), + isApk || isJar || + isAar || isWar || isEar || isZip); // Set up the filtered jar writers. - writer = wrapInJarWriter(writer, isZip, zipFilter, ".zip", isJar || isWar || isEar); - writer = wrapInJarWriter(writer, isEar, earFilter, ".ear", isJar || isWar); - writer = wrapInJarWriter(writer, isWar, warFilter, ".war", isJar); - writer = wrapInJarWriter(writer, isJar, jarFilter, ".jar", false); + writer = wrapInJarWriter(writer, isZip, zipFilter, ".zip", isApk || isJar || isAar || isWar || isEar); + writer = wrapInJarWriter(writer, isEar, earFilter, ".ear", isApk || isJar || isAar || isWar); + writer = wrapInJarWriter(writer, isWar, warFilter, ".war", isApk || isJar || isAar); + writer = wrapInJarWriter(writer, isAar, aarFilter, ".aar", isApk || isJar); + writer = wrapInJarWriter(writer, isJar, jarFilter, ".jar", isApk); + writer = wrapInJarWriter(writer, isApk, apkFilter, ".apk", false); // Add a filter, if specified. writer = filter != null? diff --git a/src/proguard/DescriptorKeepChecker.java b/src/proguard/DescriptorKeepChecker.java index fcd80b2..1b46dce 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ import proguard.optimize.*; import java.util.List; - /** * This class checks whether classes referenced by class members that are * marked to be kept are marked to be kept too. diff --git a/src/proguard/DuplicateClassPrinter.java b/src/proguard/DuplicateClassPrinter.java index 7a071ce..b849d7a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 7309843..86d7110 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/FullyQualifiedClassNameChecker.java b/src/proguard/FullyQualifiedClassNameChecker.java index eb1865a..6b6a3ad 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -36,6 +36,9 @@ public class FullyQualifiedClassNameChecker extends SimplifiedVisitor implements ClassVisitor { + private static final String INVALID_CLASS_EXTENSION = ClassUtil.internalClassName(ClassConstants.CLASS_FILE_EXTENSION); + + private final ClassPool programClassPool; private final ClassPool libraryClassPool; private final WarningPrinter notePrinter; @@ -157,10 +160,16 @@ implements ClassVisitor "Note: the configuration refers to the unknown class '" + ClassUtil.externalClassName(className) + "'"); + // Strip "/class" or replace the package name by a wildcard. + int lastSeparatorIndex = + className.lastIndexOf(ClassConstants.PACKAGE_SEPARATOR); + String fullyQualifiedClassName = - "**" + ClassConstants.INTERNAL_PACKAGE_SEPARATOR + - className.substring(className.lastIndexOf(ClassConstants.INTERNAL_PACKAGE_SEPARATOR)+1); + className.endsWith(INVALID_CLASS_EXTENSION) ? + className.substring(0, lastSeparatorIndex) : + "**" + ClassConstants.PACKAGE_SEPARATOR + className.substring(lastSeparatorIndex + 1); + // Suggest matching classes. ClassNameFilter classNameFilter = new ClassNameFilter(fullyQualifiedClassName, this); diff --git a/src/proguard/GPL.java b/src/proguard/GPL.java index 51220b8..5c7ebc7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -170,17 +170,12 @@ public class GPL 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"); + packageName.startsWith("eclipseme"); } diff --git a/src/proguard/GetAnnotationChecker.java b/src/proguard/GetAnnotationChecker.java new file mode 100644 index 0000000..bf6787d --- /dev/null +++ b/src/proguard/GetAnnotationChecker.java @@ -0,0 +1,80 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.*; +import proguard.classfile.constant.*; +import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.util.*; + +/** + * This constant visitor checks whether visited method references try to + * access annotations. + * + * @author Eric Lafortune + */ +public class GetAnnotationChecker +extends SimplifiedVisitor +implements ConstantVisitor +{ + private final WarningPrinter notePrinter; + + + /** + * Creates a new GetAnnotationChecker. + */ + public GetAnnotationChecker(WarningPrinter notePrinter) + { + this.notePrinter = notePrinter; + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) + { + String className = methodrefConstant.getClassName(clazz); + + if (className.equals(ClassConstants.NAME_JAVA_LANG_CLASS) || + className.equals(ClassConstants.NAME_JAVA_LANG_REFLECT_FIELD) || + className.equals(ClassConstants.NAME_JAVA_LANG_REFLECT_METHOD)) + { + String methodName = methodrefConstant.getName(clazz); + + if (methodName.equals(ClassConstants.METHOD_NAME_GET_ANNOTATION) || + methodName.equals(ClassConstants.METHOD_NAME_GET_ANNOTATIONS) || + methodName.equals(ClassConstants.METHOD_NAME_GET_DECLARED_ANNOTATIONS) || + methodName.equals(ClassConstants.METHOD_NAME_GET_PARAMETER_ANNOTATIONS)) + { + notePrinter.print(clazz.getName(), + "Note: " + + ClassUtil.externalClassName(clazz.getName()) + + " calls '" + + ClassUtil.externalShortClassName(ClassUtil.externalClassName(className)) + + "." + + methodName + "'"); + } + } + } +} diff --git a/src/proguard/GetEnclosingClassChecker.java b/src/proguard/GetEnclosingClassChecker.java new file mode 100644 index 0000000..a21bc1a --- /dev/null +++ b/src/proguard/GetEnclosingClassChecker.java @@ -0,0 +1,76 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.*; +import proguard.classfile.constant.*; +import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.util.*; + +/** + * This constant visitor checks whether visited method references try to + * access enclosing classes. + * + * @author Eric Lafortune + */ +public class GetEnclosingClassChecker +extends SimplifiedVisitor +implements ConstantVisitor +{ + private final WarningPrinter notePrinter; + + + /** + * Creates a new GetEnclosingMethodChecker. + */ + public GetEnclosingClassChecker(WarningPrinter notePrinter) + { + this.notePrinter = notePrinter; + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) + { + String className = methodrefConstant.getClassName(clazz); + + if (className.equals(ClassConstants.NAME_JAVA_LANG_CLASS)) + { + String methodName = methodrefConstant.getName(clazz); + + if (methodName.equals(ClassConstants.METHOD_NAME_CLASS_GET_ENCLOSING_CLASS) || + methodName.equals(ClassConstants.METHOD_NAME_CLASS_GET_DECLARING_CLASS)) + { + notePrinter.print(clazz.getName(), + "Note: " + + ClassUtil.externalClassName(clazz.getName()) + + " calls '" + + ClassUtil.externalShortClassName(ClassUtil.externalClassName(className)) + + "." + + methodName + "'"); + } + } + } +} diff --git a/src/proguard/GetEnclosingMethodChecker.java b/src/proguard/GetEnclosingMethodChecker.java new file mode 100644 index 0000000..e833042 --- /dev/null +++ b/src/proguard/GetEnclosingMethodChecker.java @@ -0,0 +1,76 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.*; +import proguard.classfile.constant.*; +import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.util.*; + +/** + * This constant visitor checks whether visited method references try to + * access enclosing methods. + * + * @author Eric Lafortune + */ +public class GetEnclosingMethodChecker +extends SimplifiedVisitor +implements ConstantVisitor +{ + private final WarningPrinter notePrinter; + + + /** + * Creates a new GetEnclosingMethodChecker. + */ + public GetEnclosingMethodChecker(WarningPrinter notePrinter) + { + this.notePrinter = notePrinter; + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) + { + String className = methodrefConstant.getClassName(clazz); + + if (className.equals(ClassConstants.NAME_JAVA_LANG_CLASS)) + { + String methodName = methodrefConstant.getName(clazz); + + if (methodName.equals(ClassConstants.METHOD_NAME_CLASS_GET_ENCLOSING_CONSTRUCTOR) || + methodName.equals(ClassConstants.METHOD_NAME_CLASS_GET_ENCLOSING_METHOD)) + { + notePrinter.print(clazz.getName(), + "Note: " + + ClassUtil.externalClassName(clazz.getName()) + + " calls '" + + ClassUtil.externalShortClassName(ClassUtil.externalClassName(className)) + + "." + + methodName + "'"); + } + } + } +} diff --git a/src/proguard/GetSignatureChecker.java b/src/proguard/GetSignatureChecker.java new file mode 100644 index 0000000..510d833 --- /dev/null +++ b/src/proguard/GetSignatureChecker.java @@ -0,0 +1,78 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.*; +import proguard.classfile.constant.*; +import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.util.*; + +/** + * This constant visitor checks whether visited method references try to + * access signatures. + * + * @author Eric Lafortune + */ +public class GetSignatureChecker +extends SimplifiedVisitor +implements ConstantVisitor +{ + private final WarningPrinter notePrinter; + + + /** + * Creates a new GetSignatureChecker. + */ + public GetSignatureChecker(WarningPrinter notePrinter) + { + this.notePrinter = notePrinter; + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) + { + String className = methodrefConstant.getClassName(clazz); + + if (className.equals(ClassConstants.NAME_JAVA_LANG_CLASS) || + className.equals(ClassConstants.NAME_JAVA_LANG_REFLECT_FIELD) || + className.equals(ClassConstants.NAME_JAVA_LANG_REFLECT_METHOD)) + { + String methodName = methodrefConstant.getName(clazz); + + if (methodName.startsWith(ClassConstants.METHOD_NAME_GET_TYPE_PREFIX) || + methodName.startsWith(ClassConstants.METHOD_NAME_GET_GENERIC_PREFIX)) + { + notePrinter.print(clazz.getName(), + "Note: " + + ClassUtil.externalClassName(clazz.getName()) + + " calls '" + + ClassUtil.externalShortClassName(ClassUtil.externalClassName(className)) + + "." + + methodName + "'"); + } + } + } +} diff --git a/src/proguard/Initializer.java b/src/proguard/Initializer.java index 405c06d..6159c7b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,10 +20,10 @@ */ package proguard; -import proguard.classfile.ClassPool; -import proguard.classfile.attribute.annotation.visitor.*; +import proguard.classfile.*; +import proguard.classfile.attribute.annotation.visitor.AllElementValueVisitor; import proguard.classfile.attribute.visitor.AllAttributeVisitor; -import proguard.classfile.constant.visitor.*; +import proguard.classfile.constant.visitor.AllConstantVisitor; import proguard.classfile.instruction.visitor.AllInstructionVisitor; import proguard.classfile.util.*; import proguard.classfile.visitor.*; @@ -63,13 +63,54 @@ public class Initializer // 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); + FullyQualifiedClassNameChecker fullyQualifiedClassNameChecker = + new FullyQualifiedClassNameChecker(programClassPool, + libraryClassPool, + fullyQualifiedClassNameNotePrinter); + + fullyQualifiedClassNameChecker.checkClassSpecifications(configuration.keep); + fullyQualifiedClassNameChecker.checkClassSpecifications(configuration.assumeNoSideEffects); + + StringMatcher keepAttributesMatcher = configuration.keepAttributes != null ? + new ListParser(new NameParser()).parse(configuration.keepAttributes) : + new EmptyStringMatcher(); + + WarningPrinter getAnnotationNotePrinter = new WarningPrinter(System.out, configuration.note); + + if (!keepAttributesMatcher.matches(ClassConstants.ATTR_RuntimeVisibleAnnotations)) + { + programClassPool.classesAccept( + new AllConstantVisitor( + new GetAnnotationChecker(getAnnotationNotePrinter))); + } + + WarningPrinter getSignatureNotePrinter = new WarningPrinter(System.out, configuration.note); + + if (!keepAttributesMatcher.matches(ClassConstants.ATTR_Signature)) + { + programClassPool.classesAccept( + new AllConstantVisitor( + new GetSignatureChecker(getSignatureNotePrinter))); + } - new KeepClassMemberChecker(keepClassMemberNotePrinter).checkClassSpecifications(configuration.keep); + WarningPrinter getEnclosingClassNotePrinter = new WarningPrinter(System.out, configuration.note); + + if (!keepAttributesMatcher.matches(ClassConstants.ATTR_InnerClasses)) + { + programClassPool.classesAccept( + new AllConstantVisitor( + new GetEnclosingClassChecker(getEnclosingClassNotePrinter))); + } + + WarningPrinter getEnclosingMethodNotePrinter = new WarningPrinter(System.out, configuration.note); + + if (!keepAttributesMatcher.matches(ClassConstants.ATTR_EnclosingMethod)) + { + programClassPool.classesAccept( + new AllConstantVisitor( + new GetEnclosingMethodChecker(getEnclosingMethodNotePrinter))); + } // Construct a reduced library class pool with only those library // classes whose hierarchies are referenced by the program classes. @@ -172,18 +213,11 @@ public class Initializer libraryClassPool)))); } - // Check for unkept descriptor classes of kept class members. - WarningPrinter descriptorKeepNotePrinter = new WarningPrinter(System.out, configuration.note); - - new DescriptorKeepChecker(programClassPool, - libraryClassPool, - descriptorKeepNotePrinter).checkClassSpecifications(configuration.keep); - // Initialize the class references of library class members. if (reducedLibraryClassPool != null) { // Collect the library classes that are referenced by program - // classes, directly or indirectly, with or without introspection. + // classes, directly or indirectly, with or without reflection. programClassPool.classesAccept( new ReferencedClassVisitor( new LibraryClassFilter( @@ -241,6 +275,30 @@ public class Initializer programClassPool.classesAccept(new StringSharer()); libraryClassPool.classesAccept(new StringSharer()); + // Check for any unmatched class members. + WarningPrinter classMemberNotePrinter = new WarningPrinter(System.out, configuration.note); + + ClassMemberChecker classMemberChecker = + new ClassMemberChecker(programClassPool, + classMemberNotePrinter); + + classMemberChecker.checkClassSpecifications(configuration.keep); + classMemberChecker.checkClassSpecifications(configuration.assumeNoSideEffects); + + // Check for unkept descriptor classes of kept class members. + WarningPrinter descriptorKeepNotePrinter = new WarningPrinter(System.out, configuration.note); + + new DescriptorKeepChecker(programClassPool, + libraryClassPool, + descriptorKeepNotePrinter).checkClassSpecifications(configuration.keep); + + // Check for keep options that only match library classes. + WarningPrinter libraryKeepNotePrinter = new WarningPrinter(System.out, configuration.note); + + new LibraryKeepChecker(programClassPool, + libraryClassPool, + libraryKeepNotePrinter).checkClassSpecifications(configuration.keep); + // Print out a summary of the notes, if necessary. int fullyQualifiedNoteCount = fullyQualifiedClassNameNotePrinter.getWarningCount(); if (fullyQualifiedNoteCount > 0) @@ -251,15 +309,52 @@ public class Initializer 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) + int classMemberNoteCount = classMemberNotePrinter.getWarningCount(); + if (classMemberNoteCount > 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)"); + System.out.println("Note: there were " + classMemberNoteCount + + " references to unknown class members."); + System.out.println(" You should check your configuration for typos."); + } + + int getAnnotationNoteCount = getAnnotationNotePrinter.getWarningCount(); + if (getAnnotationNoteCount > 0) + { + System.out.println("Note: there were " + getAnnotationNoteCount + + " classes trying to access annotations using reflection."); + System.out.println(" You should consider keeping the annotation attributes"); + System.out.println(" (using '-keepattributes *Annotation*')."); + System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#attributes)"); + } + + int getSignatureNoteCount = getSignatureNotePrinter.getWarningCount(); + if (getSignatureNoteCount > 0) + { + System.out.println("Note: there were " + getSignatureNoteCount + + " classes trying to access generic signatures using reflection."); + System.out.println(" You should consider keeping the signature attributes"); + System.out.println(" (using '-keepattributes Signature')."); + System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#attributes)"); + } + + int getEnclosingClassNoteCount = getEnclosingClassNotePrinter.getWarningCount(); + if (getEnclosingClassNoteCount > 0) + { + System.out.println("Note: there were " + getEnclosingClassNoteCount + + " classes trying to access enclosing classes using reflection."); + System.out.println(" You should consider keeping the inner classes attributes"); + System.out.println(" (using '-keepattributes InnerClasses')."); + System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#attributes)"); + } + + int getEnclosingMethodNoteCount = getEnclosingMethodNotePrinter.getWarningCount(); + if (getEnclosingMethodNoteCount > 0) + { + System.out.println("Note: there were " + getEnclosingMethodNoteCount + + " classes trying to access enclosing methods using reflection."); + System.out.println(" You should consider keeping the enclosing method attributes"); + System.out.println(" (using '-keepattributes InnerClasses,EnclosingMethod')."); + System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#attributes)"); } int descriptorNoteCount = descriptorKeepNotePrinter.getWarningCount(); @@ -272,6 +367,15 @@ public class Initializer System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#descriptorclass)"); } + int libraryNoteCount = libraryKeepNotePrinter.getWarningCount(); + if (libraryNoteCount > 0) + { + System.out.println("Note: there were " + libraryNoteCount + + " library classes explicitly being kept."); + System.out.println(" You don't need to keep library classes; they are already left unchanged."); + System.out.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#libraryclass)"); + } + int dynamicClassReferenceNoteCount = dynamicClassReferenceNotePrinter.getWarningCount(); if (dynamicClassReferenceNoteCount > 0) { @@ -375,7 +479,7 @@ public class Initializer configuration.warn.isEmpty() || configuration.ignoreWarnings)) { - System.out.println("Note: You're ignoring all warnings!"); + System.out.println("Note: you're ignoring all warnings!"); } // Discard unused library classes. diff --git a/src/proguard/InputReader.java b/src/proguard/InputReader.java index 707774e..503ce7e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,18 +54,6 @@ public class InputReader public void execute(ClassPool programClassPool, ClassPool libraryClassPool) throws IOException { - // Check if we have at least some input classes. - if (configuration.programJars == null) - { - throw new IOException("The input is empty. You have to specify one or more '-injars' options"); - } - - // Perform some sanity checks on the class paths. - checkInputOutput(configuration.libraryJars, - configuration.programJars); - checkInputOutput(configuration.programJars, - configuration.programJars); - WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn); WarningPrinter notePrinter = new WarningPrinter(System.out, configuration.note); @@ -115,7 +103,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)"); + System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#duplicateclass)"); } // Print out a summary of the warnings, if necessary. @@ -139,38 +127,6 @@ public class InputReader /** - * Performs some sanity checks on the class paths. - */ - private void checkInputOutput(ClassPath inputClassPath, - ClassPath outputClassPath) - throws IOException - { - if (inputClassPath == null || - outputClassPath == null) - { - return; - } - - for (int index1 = 0; index1 < inputClassPath.size(); index1++) - { - ClassPathEntry entry1 = inputClassPath.get(index1); - if (!entry1.isOutput()) - { - for (int index2 = 0; index2 < outputClassPath.size(); index2++) - { - ClassPathEntry entry2 = outputClassPath.get(index2); - if (entry2.isOutput() && - entry2.getName().equals(entry1.getName())) - { - throw new IOException("Input jars and output jars must be different ["+entry1.getName()+"]"); - } - } - } - } - } - - - /** * Reads all input entries from the given class path. */ private void readInput(String messagePrefix, diff --git a/src/proguard/KeepClassMemberChecker.java b/src/proguard/KeepClassMemberChecker.java index 3ea518e..ec976af 100644 --- a/src/proguard/KeepClassMemberChecker.java +++ b/src/proguard/KeepClassMemberChecker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +32,6 @@ import java.util.List; * @author Eric Lafortune */ public class KeepClassMemberChecker -extends SimplifiedVisitor -implements ClassVisitor { private final WarningPrinter notePrinter; @@ -49,8 +47,7 @@ implements ClassVisitor /** * 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. + * without actually specifying any, printing notes if necessary. */ public void checkClassSpecifications(List keepClassSpecifications) { @@ -73,7 +70,8 @@ implements ClassVisitor className = keepClassSpecification.extendsClassName; } - if (notePrinter.accepts(className)) + if (className == null || + notePrinter.accepts(className)) { notePrinter.print(className, "Note: the configuration doesn't specify which class members to keep for class '" + diff --git a/src/proguard/KeepClassSpecification.java b/src/proguard/KeepClassSpecification.java index a6215c5..6c46271 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 @@ public class KeepClassSpecification extends ClassSpecification { public final boolean markClasses; public final boolean markConditionally; + public final boolean markDescriptorClasses; public final boolean allowShrinking; public final boolean allowOptimization; public final boolean allowObfuscation; @@ -36,47 +37,57 @@ public class KeepClassSpecification extends ClassSpecification /** * Creates a new KeepClassSpecification for all possible classes. - * @param markClasses specifies whether to mark the classes. - * If false, only class members are marked. - * If true, the classes are marked as well. - * @param markConditionally specifies whether to mark the classes and - * class members conditionally. If true, classes - * and class members are marked, on the condition - * that all specified class members are present. - * @param allowShrinking specifies whether shrinking is allowed. - * @param allowOptimization specifies whether optimization is allowed. - * @param allowObfuscation specifies whether obfuscation is allowed. + * @param markClasses specifies whether to mark the classes. + * If false, only class members are marked. + * If true, the classes are marked as well. + * @param markConditionally specifies whether to mark the classes and + * class members conditionally. If true, + * classes and class members are marked, on + * the condition that all specified class + * members are present. + * @param markDescriptorClasses specifies whether to mark the classes in + * the descriptors of the marked class members. + * @param allowShrinking specifies whether shrinking is allowed. + * @param allowOptimization specifies whether optimization is allowed. + * @param allowObfuscation specifies whether obfuscation is allowed. */ public KeepClassSpecification(boolean markClasses, boolean markConditionally, + boolean markDescriptorClasses, boolean allowShrinking, boolean allowOptimization, boolean allowObfuscation) { - this.markClasses = markClasses; - this.markConditionally = markConditionally; - this.allowShrinking = allowShrinking; - this.allowOptimization = allowOptimization; - this.allowObfuscation = allowObfuscation; + this.markClasses = markClasses; + this.markConditionally = markConditionally; + this.markDescriptorClasses = markDescriptorClasses; + this.allowShrinking = allowShrinking; + this.allowOptimization = allowOptimization; + this.allowObfuscation = allowObfuscation; } /** * Creates a new KeepClassSpecification. - * @param markClasses specifies whether to mark the classes. - * If false, only class members are marked. - * If true, the classes are marked as well. - * @param markConditionally specifies whether to mark the classes and - * class members conditionally. If true, classes - * and class members are marked, on the condition - * that all specified class members are present. - * @param allowShrinking specifies whether shrinking is allowed. - * @param allowOptimization specifies whether optimization is allowed. - * @param allowObfuscation specifies whether obfuscation is allowed. - * @param classSpecification the specification of classes and class members. + * @param markClasses specifies whether to mark the classes. + * If false, only class members are marked. + * If true, the classes are marked as well. + * @param markConditionally specifies whether to mark the classes and + * class members conditionally. If true, + * classes and class members are marked, on + * the condition that all specified class + * members are present. + * @param markDescriptorClasses specifies whether to mark the classes in + * the descriptors of the marked class members. + * @param allowShrinking specifies whether shrinking is allowed. + * @param allowOptimization specifies whether optimization is allowed. + * @param allowObfuscation specifies whether obfuscation is allowed. + * @param classSpecification the specification of classes and class + * members. */ public KeepClassSpecification(boolean markClasses, boolean markConditionally, + boolean markDescriptorClasses, boolean allowShrinking, boolean allowOptimization, boolean allowObfuscation, @@ -84,11 +95,12 @@ public class KeepClassSpecification extends ClassSpecification { super(classSpecification); - this.markClasses = markClasses; - this.markConditionally = markConditionally; - this.allowShrinking = allowShrinking; - this.allowOptimization = allowOptimization; - this.allowObfuscation = allowObfuscation; + this.markClasses = markClasses; + this.markConditionally = markConditionally; + this.markDescriptorClasses = markDescriptorClasses; + this.allowShrinking = allowShrinking; + this.allowOptimization = allowOptimization; + this.allowObfuscation = allowObfuscation; } @@ -104,22 +116,24 @@ public class KeepClassSpecification extends ClassSpecification KeepClassSpecification other = (KeepClassSpecification)object; return - this.markClasses == other.markClasses && - this.markConditionally == other.markConditionally && - this.allowShrinking == other.allowShrinking && - this.allowOptimization == other.allowOptimization && - this.allowObfuscation == other.allowObfuscation && + this.markClasses == other.markClasses && + this.markConditionally == other.markConditionally && + this.markDescriptorClasses == other.markDescriptorClasses && + this.allowShrinking == other.allowShrinking && + this.allowOptimization == other.allowOptimization && + this.allowObfuscation == other.allowObfuscation && super.equals(other); } public int hashCode() { return - (markClasses ? 0 : 1) ^ - (markConditionally ? 0 : 2) ^ - (allowShrinking ? 0 : 4) ^ - (allowOptimization ? 0 : 8) ^ - (allowObfuscation ? 0 : 16) ^ + (markClasses ? 0 : 1) ^ + (markConditionally ? 0 : 2) ^ + (markDescriptorClasses ? 0 : 4) ^ + (allowShrinking ? 0 : 8) ^ + (allowOptimization ? 0 : 16) ^ + (allowObfuscation ? 0 : 32) ^ super.hashCode(); } diff --git a/src/proguard/LibraryKeepChecker.java b/src/proguard/LibraryKeepChecker.java new file mode 100644 index 0000000..3209539 --- /dev/null +++ b/src/proguard/LibraryKeepChecker.java @@ -0,0 +1,115 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.*; +import proguard.classfile.util.*; +import proguard.classfile.visitor.*; +import proguard.optimize.*; + +import java.util.List; + +/** + * This class checks whether some keep rules only keep library classes, no + * program classes. That is strange, because library classes never need to + * be kept explicitly. + * + * @author Eric Lafortune + */ +public class LibraryKeepChecker +implements ClassVisitor +{ + private final ClassPool programClassPool; + private final ClassPool libraryClassPool; + private final WarningPrinter notePrinter; + + // Some fields acting as parameters for the class visitor. + private String keepName; + + + /** + * Creates a new DescriptorKeepChecker. + */ + public LibraryKeepChecker(ClassPool programClassPool, + ClassPool libraryClassPool, + WarningPrinter notePrinter) + { + this.programClassPool = programClassPool; + this.libraryClassPool = libraryClassPool; + this.notePrinter = notePrinter; + } + + + /** + * Checks the classes mentioned in the given keep specifications, printing + * notes if necessary. + */ + public void checkClassSpecifications(List keepSpecifications) + { + if (keepSpecifications != null) + { + // Go over all individual keep specifications. + for (int index = 0; index < keepSpecifications.size(); index++) + { + KeepClassSpecification keepClassSpecification = + (KeepClassSpecification)keepSpecifications.get(index); + + // Is the keep specification more specific than a general + // wildcard? + keepName = keepClassSpecification.className; + if (keepName != null) + { + // Doesn't the specification match any program classes? + ClassCounter programClassCounter = new ClassCounter(); + programClassPool.accept( + ClassSpecificationVisitorFactory.createClassPoolVisitor(keepClassSpecification, + programClassCounter, + null)); + if (programClassCounter.getCount() == 0) + { + // Print out notes about any matched library classes. + libraryClassPool.accept( + ClassSpecificationVisitorFactory.createClassPoolVisitor(keepClassSpecification, + this, + null)); + } + } + } + } + } + + + // Implementations for ClassVisitor. + + public void visitProgramClass(ProgramClass programClass) {} + + + public void visitLibraryClass(LibraryClass libraryClass) + { + String className = libraryClass.getName(); + notePrinter.print(className, + "Note: the configuration explicitly specifies '" + + ClassUtil.externalClassName(keepName) + + "' to keep library class '" + + ClassUtil.externalClassName(className) + + "'"); + } +} diff --git a/src/proguard/LineWordReader.java b/src/proguard/LineWordReader.java index 64a228c..b39f2fe 100644 --- a/src/proguard/LineWordReader.java +++ b/src/proguard/LineWordReader.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/MemberSpecification.java b/src/proguard/MemberSpecification.java index e771fde..9e4d671 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 c4467cf..3feb1c4 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,87 +55,6 @@ public class OutputWriter { ClassPath programJars = configuration.programJars; - // Perform a check on the first jar. - ClassPathEntry firstEntry = programJars.get(0); - if (firstEntry.isOutput()) - { - throw new IOException("The output jar [" + firstEntry.getName() + - "] must be specified after an input jar, or it will be empty."); - } - - // 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()) - { - if (entry.getFilter() == null && - entry.getJarFilter() == null && - entry.getWarFilter() == null && - entry.getEarFilter() == null && - entry.getZipFilter() == null && - programJars.get(index + 1).isOutput()) - { - throw new IOException("The output jar [" + entry.getName() + - "] must have a filter, or all subsequent output jars will be empty."); - } - } - } - - // 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); - - if (!otherEntry.isOutput() && - entry.getFile().equals(otherEntry.getFile())) - { - throw new IOException("The output jar [" + entry.getName() + - "] must be different from all input jars."); - } - } - } - } - - // 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; @@ -200,30 +119,34 @@ public class OutputWriter DataEntryReader resourceRewriter = resourceCopier; - // Wrap the resource writer with a filter and a data entry rewriter, - // if required. - if (configuration.adaptResourceFileContents != null) - { - resourceRewriter = - new NameFilter(configuration.adaptResourceFileContents, - new NameFilter("META-INF/MANIFEST.MF,META-INF/*.SF", - new ManifestRewriter(programClassPool, writer), - new DataEntryRewriter(programClassPool, writer)), - resourceRewriter); - } - - // Wrap the resource writer with a filter and a data entry renamer, - // if required. - if (configuration.adaptResourceFileNames != null) + // Adapt resource file contents and names, if necessary. + if (configuration.obfuscate) { - Map packagePrefixMap = createPackagePrefixMap(programClassPool); + // Wrap the resource writer with a filter and a data entry + // rewriter, if required. + if (configuration.adaptResourceFileContents != null) + { + resourceRewriter = + new NameFilter(configuration.adaptResourceFileContents, + new NameFilter("META-INF/MANIFEST.MF,META-INF/*.SF", + new ManifestRewriter(programClassPool, writer), + new DataEntryRewriter(programClassPool, writer)), + resourceRewriter); + } - resourceRewriter = - new NameFilter(configuration.adaptResourceFileNames, - new DataEntryObfuscator(programClassPool, - packagePrefixMap, - resourceRewriter), - resourceRewriter); + // Wrap the resource writer with a filter and a data entry + // renamer, if required. + if (configuration.adaptResourceFileNames != null) + { + Map packagePrefixMap = createPackagePrefixMap(programClassPool); + + resourceRewriter = + new NameFilter(configuration.adaptResourceFileNames, + new DataEntryObfuscator(programClassPool, + packagePrefixMap, + resourceRewriter), + resourceRewriter); + } } DataEntryReader directoryRewriter = null; diff --git a/src/proguard/ParseException.java b/src/proguard/ParseException.java index b4af6c2..4cb5e70 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 f9dbf54..b35921c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,16 +20,16 @@ */ package proguard; -import proguard.classfile.ClassPool; -import proguard.classfile.editor.ClassElementSorter; +import proguard.classfile.*; +import proguard.classfile.attribute.visitor.AllAttributeVisitor; +import proguard.classfile.editor.*; import proguard.classfile.visitor.*; import proguard.obfuscate.Obfuscator; -import proguard.optimize.*; +import proguard.optimize.Optimizer; import proguard.preverify.*; import proguard.shrink.Shrinker; import java.io.*; -import java.util.Properties; /** * Tool for shrinking, optimizing, obfuscating, and preverifying Java classes. @@ -38,7 +38,7 @@ import java.util.Properties; */ public class ProGuard { - public static final String VERSION = "ProGuard, version 4.10"; + public static final String VERSION = "ProGuard, version 5.1"; private final Configuration configuration; private ClassPool programClassPool = new ClassPool(); @@ -69,6 +69,8 @@ public class ProGuard printConfiguration(); } + new ConfigurationChecker(configuration).check(); + if (configuration.programJars != null && configuration.programJars.hasOutput() && new UpToDateChecker(configuration).check()) @@ -78,6 +80,14 @@ public class ProGuard readInput(); + if (configuration.shrink || + configuration.optimize || + configuration.obfuscate || + configuration.preverify) + { + clearPreverification(); + } + if (configuration.printSeeds != null || configuration.shrink || configuration.optimize || @@ -336,6 +346,19 @@ public class ProGuard /** + * Clears any JSE preverification information from the program classes. + */ + private void clearPreverification() + { + programClassPool.classesAccept( + new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_6, + new AllMethodVisitor( + new AllAttributeVisitor( + new NamedAttributeDeleter(ClassConstants.ATTR_StackMapTable))))); + } + + + /** * Performs the preverification step. */ private void preverify() diff --git a/src/proguard/SeedPrinter.java b/src/proguard/SeedPrinter.java index 8ed74b6..7418aee 100644 --- a/src/proguard/SeedPrinter.java +++ b/src/proguard/SeedPrinter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,16 +21,10 @@ 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. diff --git a/src/proguard/SubclassedClassFilter.java b/src/proguard/SubclassedClassFilter.java index 1b9c1fe..e851a2b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 675f0df..b0e71c1 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 7f5e7a6..f0b2b81 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/WordReader.java b/src/proguard/WordReader.java index 110fce3..f375057 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/ant/ClassPathElement.java b/src/proguard/ant/ClassPathElement.java index b496123..ef5b510 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 @@ import java.io.File; public class ClassPathElement extends Path { private String filter; + private String apkFilter; private String jarFilter; + private String aarFilter; private String warFilter; private String earFilter; private String zipFilter; @@ -120,7 +122,9 @@ public class ClassPathElement extends Path new ClassPathEntry(file.isAbsolute() ? file : new File(baseDir, fileName), output); entry.setFilter(ListUtil.commaSeparatedList(filter)); + entry.setApkFilter(ListUtil.commaSeparatedList(apkFilter)); entry.setJarFilter(ListUtil.commaSeparatedList(jarFilter)); + entry.setAarFilter(ListUtil.commaSeparatedList(aarFilter)); entry.setWarFilter(ListUtil.commaSeparatedList(warFilter)); entry.setEarFilter(ListUtil.commaSeparatedList(earFilter)); entry.setZipFilter(ListUtil.commaSeparatedList(zipFilter)); @@ -166,12 +170,24 @@ public class ClassPathElement extends Path } + public void setApkfilter(String apkFilter) + { + this.apkFilter = apkFilter; + } + + public void setJarfilter(String jarFilter) { this.jarFilter = jarFilter; } + public void setAarfilter(String aarFilter) + { + this.aarFilter = aarFilter; + } + + public void setWarfilter(String warFilter) { this.warFilter = warFilter; diff --git a/src/proguard/ant/ClassSpecificationElement.java b/src/proguard/ant/ClassSpecificationElement.java index c07e101..146bf09 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.ant; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.types.DataType; import proguard.*; -import proguard.classfile.ClassConstants; +import proguard.classfile.*; import proguard.classfile.util.ClassUtil; import java.util.*; @@ -219,12 +219,12 @@ public class ClassSpecificationElement extends DataType 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; + strippedToken.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC : + strippedToken.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL : + strippedToken.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT : + strippedToken.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC : + strippedToken.equals(JavaConstants.ACC_ANNOTATION) ? ClassConstants.ACC_ANNOTATTION : + 0; if (accessFlag == 0) { @@ -239,12 +239,13 @@ public class ClassSpecificationElement extends DataType 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; + type.equals("class") ? 0 : + type.equals( JavaConstants.ACC_INTERFACE) || + type.equals("!" + JavaConstants.ACC_INTERFACE) ? ClassConstants.ACC_INTERFACE : + type.equals( JavaConstants.ACC_ENUM) || + type.equals("!" + JavaConstants.ACC_ENUM) ? ClassConstants.ACC_ENUM : + -1; + if (accessFlag == -1) { throw new BuildException("Incorrect class type ["+type+"]"); diff --git a/src/proguard/ant/ConfigurationElement.java b/src/proguard/ant/ConfigurationElement.java index d184aef..f6e7be8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ package proguard.ant; import org.apache.tools.ant.*; import org.apache.tools.ant.types.*; import proguard.*; -import proguard.util.ListUtil; import java.io.*; import java.util.Properties; diff --git a/src/proguard/ant/ConfigurationTask.java b/src/proguard/ant/ConfigurationTask.java index 376a1a1..0bd1b35 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/FilterElement.java b/src/proguard/ant/FilterElement.java index ab3364a..b31313f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 feabc18..06c3ff0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 @@ import java.util.List; */ public class KeepSpecificationElement extends ClassSpecificationElement { + private boolean markDescriptorClasses; private boolean allowShrinking; private boolean allowOptimization; private boolean allowObfuscation; @@ -56,6 +57,7 @@ public class KeepSpecificationElement extends ClassSpecificationElement KeepClassSpecification keepClassSpecification = new KeepClassSpecification(markClasses, markConditionally, + markDescriptorClasses, allowShrinking, allowOptimization, allowObfuscation, @@ -68,6 +70,12 @@ public class KeepSpecificationElement extends ClassSpecificationElement // Ant task attributes. + public void setIncludedescriptorclasses(boolean markDescriptorClasses) + { + this.markDescriptorClasses = markDescriptorClasses; + } + + public void setAllowshrinking(boolean allowShrinking) { this.allowShrinking = allowShrinking; diff --git a/src/proguard/ant/MemberSpecificationElement.java b/src/proguard/ant/MemberSpecificationElement.java index 9762009..2cfa697 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.ant; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.types.DataType; import proguard.MemberSpecification; -import proguard.classfile.ClassConstants; +import proguard.classfile.*; import proguard.classfile.util.ClassUtil; import proguard.util.ListUtil; @@ -87,10 +87,10 @@ public class MemberSpecificationElement extends DataType if (parameters != null) { - type = ClassConstants.EXTERNAL_TYPE_VOID; + type = JavaConstants.TYPE_VOID; } - name = ClassConstants.INTERNAL_METHOD_NAME_INIT; + name = ClassConstants.METHOD_NAME_INIT; } else if ((type != null) ^ (parameters != null)) { @@ -187,21 +187,21 @@ public class MemberSpecificationElement extends DataType 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; + strippedToken.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC : + strippedToken.equals(JavaConstants.ACC_PRIVATE) ? ClassConstants.ACC_PRIVATE : + strippedToken.equals(JavaConstants.ACC_PROTECTED) ? ClassConstants.ACC_PROTECTED : + strippedToken.equals(JavaConstants.ACC_STATIC) ? ClassConstants.ACC_STATIC : + strippedToken.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL : + strippedToken.equals(JavaConstants.ACC_SYNCHRONIZED) ? ClassConstants.ACC_SYNCHRONIZED : + strippedToken.equals(JavaConstants.ACC_VOLATILE) ? ClassConstants.ACC_VOLATILE : + strippedToken.equals(JavaConstants.ACC_TRANSIENT) ? ClassConstants.ACC_TRANSIENT : + strippedToken.equals(JavaConstants.ACC_BRIDGE) ? ClassConstants.ACC_BRIDGE : + strippedToken.equals(JavaConstants.ACC_VARARGS) ? ClassConstants.ACC_VARARGS : + strippedToken.equals(JavaConstants.ACC_NATIVE) ? ClassConstants.ACC_NATIVE : + strippedToken.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT : + strippedToken.equals(JavaConstants.ACC_STRICT) ? ClassConstants.ACC_STRICT : + strippedToken.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC : + 0; if (accessFlag == 0) { diff --git a/src/proguard/ant/ProGuardTask.java b/src/proguard/ant/ProGuardTask.java index 7ab1cdf..f26f1b2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,18 +51,18 @@ public class ProGuardTask extends ConfigurationTask { parser.parse(configuration); } - catch (ParseException ex) + catch (ParseException e) { - throw new BuildException(ex.getMessage()); + throw new BuildException(e.getMessage(), e); } finally { parser.close(); } } - catch (IOException ex) + catch (IOException e) { - throw new BuildException(ex.getMessage()); + throw new BuildException(e.getMessage(), e); } } @@ -315,9 +315,9 @@ public class ProGuardTask extends ConfigurationTask ProGuard proGuard = new ProGuard(configuration); proGuard.execute(); } - catch (IOException ex) + catch (IOException e) { - throw new BuildException(ex.getMessage()); + throw new BuildException(e.getMessage(), e); } } diff --git a/src/proguard/classfile/ClassConstants.java b/src/proguard/classfile/ClassConstants.java index 59580c5..7220285 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,118 +21,94 @@ package proguard.classfile; /** - * Constants used in representing a Java class (*.class). + * Constants used in representing a Java class file (*.class). * * @author Eric Lafortune */ -public interface ClassConstants +public class ClassConstants { public static final String CLASS_FILE_EXTENSION = ".class"; public static final int MAGIC = 0xCAFEBABE; - public static final int INTERNAL_CLASS_VERSION_1_0_MAJOR = 45; - public static final int INTERNAL_CLASS_VERSION_1_0_MINOR = 3; - public static final int INTERNAL_CLASS_VERSION_1_2_MAJOR = 46; - public static final int INTERNAL_CLASS_VERSION_1_2_MINOR = 0; - public static final int INTERNAL_CLASS_VERSION_1_3_MAJOR = 47; - public static final int INTERNAL_CLASS_VERSION_1_3_MINOR = 0; - public static final int INTERNAL_CLASS_VERSION_1_4_MAJOR = 48; - public static final int INTERNAL_CLASS_VERSION_1_4_MINOR = 0; - public static final int INTERNAL_CLASS_VERSION_1_5_MAJOR = 49; - 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 CLASS_VERSION_1_0_MAJOR = 45; + public static final int CLASS_VERSION_1_0_MINOR = 3; + public static final int CLASS_VERSION_1_2_MAJOR = 46; + public static final int CLASS_VERSION_1_2_MINOR = 0; + public static final int CLASS_VERSION_1_3_MAJOR = 47; + public static final int CLASS_VERSION_1_3_MINOR = 0; + public static final int CLASS_VERSION_1_4_MAJOR = 48; + public static final int CLASS_VERSION_1_4_MINOR = 0; + public static final int CLASS_VERSION_1_5_MAJOR = 49; + public static final int CLASS_VERSION_1_5_MINOR = 0; + public static final int CLASS_VERSION_1_6_MAJOR = 50; + public static final int CLASS_VERSION_1_6_MINOR = 0; + public static final int CLASS_VERSION_1_7_MAJOR = 51; + public static final int CLASS_VERSION_1_7_MINOR = 0; + public static final int CLASS_VERSION_1_8_MAJOR = 52; + public static final int CLASS_VERSION_1_8_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; - public static final int INTERNAL_CLASS_VERSION_1_3 = (INTERNAL_CLASS_VERSION_1_3_MAJOR << 16) | INTERNAL_CLASS_VERSION_1_3_MINOR; - 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 int CLASS_VERSION_1_0 = (CLASS_VERSION_1_0_MAJOR << 16) | CLASS_VERSION_1_0_MINOR; + public static final int CLASS_VERSION_1_2 = (CLASS_VERSION_1_2_MAJOR << 16) | CLASS_VERSION_1_2_MINOR; + public static final int CLASS_VERSION_1_3 = (CLASS_VERSION_1_3_MAJOR << 16) | CLASS_VERSION_1_3_MINOR; + public static final int CLASS_VERSION_1_4 = (CLASS_VERSION_1_4_MAJOR << 16) | CLASS_VERSION_1_4_MINOR; + public static final int CLASS_VERSION_1_5 = (CLASS_VERSION_1_5_MAJOR << 16) | CLASS_VERSION_1_5_MINOR; + public static final int CLASS_VERSION_1_6 = (CLASS_VERSION_1_6_MAJOR << 16) | CLASS_VERSION_1_6_MINOR; + public static final int CLASS_VERSION_1_7 = (CLASS_VERSION_1_7_MAJOR << 16) | CLASS_VERSION_1_7_MINOR; + public static final int CLASS_VERSION_1_8 = (CLASS_VERSION_1_8_MAJOR << 16) | CLASS_VERSION_1_8_MINOR; - public static final String EXTERNAL_CLASS_VERSION_1_0 = "1.0"; - public static final String EXTERNAL_CLASS_VERSION_1_1 = "1.1"; - public static final String EXTERNAL_CLASS_VERSION_1_2 = "1.2"; - public static final String EXTERNAL_CLASS_VERSION_1_3 = "1.3"; - 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 ACC_PUBLIC = 0x0001; + public static final int ACC_PRIVATE = 0x0002; + public static final int ACC_PROTECTED = 0x0004; + public static final int ACC_STATIC = 0x0008; + public static final int ACC_FINAL = 0x0010; + public static final int ACC_SUPER = 0x0020; + public static final int ACC_SYNCHRONIZED = 0x0020; + public static final int ACC_VOLATILE = 0x0040; + public static final int ACC_TRANSIENT = 0x0080; + public static final int ACC_BRIDGE = 0x0040; + public static final int ACC_VARARGS = 0x0080; + public static final int ACC_NATIVE = 0x0100; + public static final int ACC_INTERFACE = 0x0200; + public static final int ACC_ABSTRACT = 0x0400; + public static final int ACC_STRICT = 0x0800; + public static final int ACC_SYNTHETIC = 0x1000; + public static final int ACC_ANNOTATTION = 0x2000; + public static final int ACC_ENUM = 0x4000; + public static final int ACC_MANDATED = 0x8000; - public static final int INTERNAL_ACC_PUBLIC = 0x0001; - public static final int INTERNAL_ACC_PRIVATE = 0x0002; - public static final int INTERNAL_ACC_PROTECTED = 0x0004; - public static final int INTERNAL_ACC_STATIC = 0x0008; - public static final int INTERNAL_ACC_FINAL = 0x0010; - public static final int INTERNAL_ACC_SUPER = 0x0020; - public static final int INTERNAL_ACC_SYNCHRONIZED = 0x0020; - public static final int INTERNAL_ACC_VOLATILE = 0x0040; - public static final int INTERNAL_ACC_TRANSIENT = 0x0080; - public static final int INTERNAL_ACC_BRIDGE = 0x0040; - public static final int INTERNAL_ACC_VARARGS = 0x0080; - public static final int INTERNAL_ACC_NATIVE = 0x0100; - public static final int INTERNAL_ACC_INTERFACE = 0x0200; - public static final int INTERNAL_ACC_ABSTRACT = 0x0400; - public static final int INTERNAL_ACC_STRICT = 0x0800; - public static final int INTERNAL_ACC_SYNTHETIC = 0x1000; - public static final int INTERNAL_ACC_ANNOTATTION = 0x2000; - public static final int INTERNAL_ACC_ENUM = 0x4000; - - public static final int VALID_INTERNAL_ACC_CLASS = INTERNAL_ACC_PUBLIC | - INTERNAL_ACC_FINAL | - INTERNAL_ACC_SUPER | - INTERNAL_ACC_INTERFACE | - INTERNAL_ACC_ABSTRACT | - INTERNAL_ACC_SYNTHETIC | - INTERNAL_ACC_ANNOTATTION | - INTERNAL_ACC_ENUM; - public static final int VALID_INTERNAL_ACC_FIELD = INTERNAL_ACC_PUBLIC | - INTERNAL_ACC_PRIVATE | - INTERNAL_ACC_PROTECTED | - INTERNAL_ACC_STATIC | - INTERNAL_ACC_FINAL | - INTERNAL_ACC_VOLATILE | - INTERNAL_ACC_TRANSIENT | - INTERNAL_ACC_SYNTHETIC | - INTERNAL_ACC_ENUM; - public static final int VALID_INTERNAL_ACC_METHOD = INTERNAL_ACC_PUBLIC | - INTERNAL_ACC_PRIVATE | - INTERNAL_ACC_PROTECTED | - INTERNAL_ACC_STATIC | - INTERNAL_ACC_FINAL | - INTERNAL_ACC_SYNCHRONIZED | - INTERNAL_ACC_BRIDGE | - INTERNAL_ACC_VARARGS | - INTERNAL_ACC_NATIVE | - INTERNAL_ACC_ABSTRACT | - INTERNAL_ACC_STRICT | - INTERNAL_ACC_SYNTHETIC; - - public static final String EXTERNAL_ACC_PUBLIC = "public"; - public static final String EXTERNAL_ACC_PRIVATE = "private"; - public static final String EXTERNAL_ACC_PROTECTED = "protected"; - public static final String EXTERNAL_ACC_STATIC = "static"; - public static final String EXTERNAL_ACC_FINAL = "final"; - public static final String EXTERNAL_ACC_SUPER = "super"; - 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"; + public static final int VALID_ACC_CLASS = ACC_PUBLIC | + ACC_FINAL | + ACC_SUPER | + ACC_INTERFACE | + ACC_ABSTRACT | + ACC_SYNTHETIC | + ACC_ANNOTATTION | + ACC_ENUM; + public static final int VALID_ACC_FIELD = ACC_PUBLIC | + ACC_PRIVATE | + ACC_PROTECTED | + ACC_STATIC | + ACC_FINAL | + ACC_VOLATILE | + ACC_TRANSIENT | + ACC_SYNTHETIC | + ACC_ENUM; + public static final int VALID_ACC_METHOD = ACC_PUBLIC | + ACC_PRIVATE | + ACC_PROTECTED | + ACC_STATIC | + ACC_FINAL | + ACC_SYNCHRONIZED | + ACC_BRIDGE | + ACC_VARARGS | + ACC_NATIVE | + ACC_ABSTRACT | + ACC_STRICT | + ACC_SYNTHETIC; + public static final int VALID_ACC_PARAMETER = ACC_FINAL | + ACC_SYNTHETIC | + ACC_MANDATED; public static final int CONSTANT_Utf8 = 1; public static final int CONSTANT_Integer = 3; @@ -168,6 +144,7 @@ public interface ClassConstants public static final String ATTR_Synthetic = "Synthetic"; public static final String ATTR_Signature = "Signature"; public static final String ATTR_ConstantValue = "ConstantValue"; + public static final String ATTR_MethodParameters = "MethodParameters"; public static final String ATTR_Exceptions = "Exceptions"; public static final String ATTR_Code = "Code"; public static final String ATTR_StackMap = "StackMap"; @@ -179,145 +156,183 @@ public interface ClassConstants public static final String ATTR_RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations"; public static final String ATTR_RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations"; public static final String ATTR_RuntimeInvisibleParameterAnnotations = "RuntimeInvisibleParameterAnnotations"; + public static final String ATTR_RuntimeVisibleTypeAnnotations = "RuntimeVisibleTypeAnnotations"; + public static final String ATTR_RuntimeInvisibleTypeAnnotations = "RuntimeInvisibleTypeAnnotations"; public static final String ATTR_AnnotationDefault = "AnnotationDefault"; + public static final int ANNOTATION_TARGET_ParameterGenericClass = 0x00; + public static final int ANNOTATION_TARGET_ParameterGenericMethod = 0x01; + public static final int ANNOTATION_TARGET_Extends = 0x10; + public static final int ANNOTATION_TARGET_BoundGenericClass = 0x11; + public static final int ANNOTATION_TARGET_BoundGenericMethod = 0x12; + public static final int ANNOTATION_TARGET_Field = 0x13; + public static final int ANNOTATION_TARGET_Return = 0x14; + public static final int ANNOTATION_TARGET_Receiver = 0x15; + public static final int ANNOTATION_TARGET_Parameter = 0x16; + public static final int ANNOTATION_TARGET_Throws = 0x17; + public static final int ANNOTATION_TARGET_LocalVariable = 0x40; + public static final int ANNOTATION_TARGET_ResourceVariable = 0x41; + public static final int ANNOTATION_TARGET_Catch = 0x42; + public static final int ANNOTATION_TARGET_InstanceOf = 0x43; + public static final int ANNOTATION_TARGET_New = 0x44; + public static final int ANNOTATION_TARGET_MethodReferenceNew = 0x45; + public static final int ANNOTATION_TARGET_MethodReference = 0x46; + public static final int ANNOTATION_TARGET_Cast = 0x47; + public static final int ANNOTATION_TARGET_ArgumentGenericMethodNew = 0x48; + public static final int ANNOTATION_TARGET_ArgumentGenericMethod = 0x49; + public static final int ANNOTATION_TARGET_ArgumentGenericMethodReferenceNew = 0x4a; + public static final int ANNOTATION_TARGET_ArgumentGenericMethodReference = 0x4b; + 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 = '.'; - public static final char INTERNAL_PACKAGE_SEPARATOR = '/'; - public static final char INTERNAL_INNER_CLASS_SEPARATOR = '$'; - public static final char SPECIAL_CLASS_CHARACTER = '-'; - public static final char SPECIAL_MEMBER_SEPARATOR = '$'; - - public static final char EXTERNAL_METHOD_ARGUMENTS_OPEN = '('; - public static final char EXTERNAL_METHOD_ARGUMENTS_CLOSE = ')'; - public static final char EXTERNAL_METHOD_ARGUMENTS_SEPARATOR = ','; - - public static final char INTERNAL_METHOD_ARGUMENTS_OPEN = '('; - public static final char INTERNAL_METHOD_ARGUMENTS_CLOSE = ')'; + public static final char PACKAGE_SEPARATOR = '/'; + public static final char INNER_CLASS_SEPARATOR = '$'; + public static final char SPECIAL_CLASS_CHARACTER = '-'; + public static final char SPECIAL_MEMBER_SEPARATOR = '$'; - 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 char METHOD_ARGUMENTS_OPEN = '('; + public static final char METHOD_ARGUMENTS_CLOSE = ')'; - 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 PACKAGE_JAVA_LANG = "java/lang/"; + public static final String NAME_JAVA_LANG_OBJECT = "java/lang/Object"; + public static final String TYPE_JAVA_LANG_OBJECT = "Ljava/lang/Object;"; + public static final String NAME_JAVA_LANG_CLONEABLE = "java/lang/Cloneable"; + public static final String NAME_JAVA_LANG_THROWABLE = "java/lang/Throwable"; + public static final String NAME_JAVA_LANG_CLASS = "java/lang/Class"; + public static final String NAME_JAVA_LANG_STRING = "java/lang/String"; + public static final String NAME_JAVA_LANG_STRING_BUFFER = "java/lang/StringBuffer"; + public static final String NAME_JAVA_LANG_STRING_BUILDER = "java/lang/StringBuilder"; + public static final String NAME_JAVA_LANG_INVOKE_METHOD_HANDLE = "java/lang/invoke/MethodHandle"; + public static final String NAME_JAVA_LANG_INVOKE_METHOD_TYPE = "java/lang/invoke/MethodType"; + public static final String NAME_JAVA_LANG_VOID = "java/lang/Void"; + public static final String NAME_JAVA_LANG_BOOLEAN = "java/lang/Boolean"; + public static final String NAME_JAVA_LANG_BYTE = "java/lang/Byte"; + public static final String NAME_JAVA_LANG_SHORT = "java/lang/Short"; + public static final String NAME_JAVA_LANG_CHARACTER = "java/lang/Character"; + public static final String NAME_JAVA_LANG_INTEGER = "java/lang/Integer"; + public static final String NAME_JAVA_LANG_LONG = "java/lang/Long"; + public static final String NAME_JAVA_LANG_FLOAT = "java/lang/Float"; + public static final String NAME_JAVA_LANG_DOUBLE = "java/lang/Double"; + public static final String NAME_JAVA_LANG_MATH = "java/lang/Math"; + public static final String NAME_JAVA_LANG_SYSTEM = "java/lang/System"; + public static final String NAME_JAVA_LANG_RUNTIME = "java/lang/Runtime"; + public static final String NAME_JAVA_LANG_REFLECT_ARRAY = "java/lang/reflect/Array"; + public static final String NAME_JAVA_LANG_REFLECT_FIELD = "java/lang/reflect/Field"; + public static final String NAME_JAVA_LANG_REFLECT_METHOD = "java/lang/reflect/Method"; + public static final String NAME_JAVA_LANG_REFLECT_CONSTRUCTOR = "java/lang/reflect/Constructor"; + public static final String NAME_JAVA_LANG_REFLECT_ACCESSIBLE_OBJECT = "java/lang/reflect/AccessibleObject"; + public static final String NAME_JAVA_IO_SERIALIZABLE = "java/io/Serializable"; - 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 NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicIntegerFieldUpdater"; + public static final String NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_LONG_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicLongFieldUpdater"; + public static final String NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_REFERENCE_FIELD_UPDATER = "java/util/concurrent/atomic/AtomicReferenceFieldUpdater"; - 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 METHOD_NAME_INIT = "<init>"; + public static final String METHOD_TYPE_INIT = "()V"; + public static final String METHOD_NAME_CLINIT = "<clinit>"; + public static final String METHOD_TYPE_CLINIT = "()V"; - 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 METHOD_NAME_CLASS_FOR_NAME = "forName"; + public static final String METHOD_TYPE_CLASS_FOR_NAME = "(Ljava/lang/String;)Ljava/lang/Class;"; + public static final String METHOD_NAME_CLASS_GET_COMPONENT_TYPE = "getComponentType"; + public static final String METHOD_TYPE_CLASS_GET_COMPONENT_TYPE = "()Ljava/lang/Class;"; + public static final String METHOD_NAME_CLASS_GET_FIELD = "getField"; + public static final String METHOD_TYPE_CLASS_GET_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;"; + public static final String METHOD_NAME_CLASS_GET_DECLARED_FIELD = "getDeclaredField"; + public static final String METHOD_TYPE_CLASS_GET_DECLARED_FIELD = "(Ljava/lang/String;)Ljava/lang/reflect/Field;"; + public static final String CONSTRUCTOR_NAME_CLASS_GET_CONSTRUCTOR = "getConstructor"; + public static final String CONSTRUCTOR_TYPE_CLASS_GET_CONSTRUCTOR = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;"; + public static final String CONSTRUCTOR_NAME_CLASS_GET_DECLARED_CONSTRUCTOR = "getDeclaredConstructor"; + public static final String CONSTRUCTOR_TYPE_CLASS_GET_DECLARED_CONSTRUCTOR = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;"; + public static final String METHOD_NAME_CLASS_GET_METHOD = "getMethod"; + public static final String METHOD_TYPE_CLASS_GET_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"; + public static final String METHOD_NAME_CLASS_GET_DECLARED_METHOD = "getDeclaredMethod"; + public static final String METHOD_TYPE_CLASS_GET_DECLARED_METHOD = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"; + public static final String METHOD_NAME_CLASS_GET_DECLARING_CLASS = "getDeclaringClass"; + public static final String METHOD_NAME_CLASS_GET_ENCLOSING_CLASS = "getEnclosingClass"; + public static final String METHOD_NAME_CLASS_GET_ENCLOSING_CONSTRUCTOR = "getEnclosingConstructor"; + public static final String METHOD_NAME_CLASS_GET_ENCLOSING_METHOD = "getEnclosingMethod"; + public static final String METHOD_NAME_GET_ANNOTATION = "getAnnotation"; + public static final String METHOD_NAME_GET_ANNOTATIONS = "getAnnotations"; + public static final String METHOD_NAME_GET_DECLARED_ANNOTATIONS = "getDeclaredAnnotations"; + public static final String METHOD_NAME_GET_PARAMETER_ANNOTATIONS = "getParameterAnnotations"; + public static final String METHOD_NAME_GET_TYPE_PREFIX = "getType"; + public static final String METHOD_NAME_GET_GENERIC_PREFIX = "getGeneric"; + public static final String METHOD_NAME_NEW_UPDATER = "newUpdater"; + public static final String METHOD_TYPE_NEW_INTEGER_UPDATER = "(Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicIntegerFieldUpdater;"; + public static final String METHOD_TYPE_NEW_LONG_UPDATER = "(Ljava/lang/Class;Ljava/lang/String;)Ljava/util/concurrent/atomic/AtomicLongFieldUpdater;"; + public static final String 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_TYPE_INIT_ENUM = "(Ljava/lang/String;I)V"; + public static final String METHOD_NAME_DOT_CLASS_JAVAC = "class$"; + public static final String METHOD_TYPE_DOT_CLASS_JAVAC = "(Ljava/lang/String;)Ljava/lang/Class;"; + public static final String METHOD_NAME_DOT_CLASS_JIKES = "class"; + public static final String METHOD_TYPE_DOT_CLASS_JIKES = "(Ljava/lang/String;Z)Ljava/lang/Class;"; - 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 METHOD_TYPE_INIT_ENUM = "(Ljava/lang/String;I)V"; - 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 METHOD_NAME_NEW_INSTANCE = "newInstance"; + public static final String METHOD_TYPE_NEW_INSTANCE = "()Ljava/lang/Object;"; - 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 String METHOD_NAME_EQUALS = "equals"; + public static final String METHOD_TYPE_EQUALS = "(Ljava/lang/Object;)Z"; + public static final String METHOD_NAME_LENGTH = "length"; + public static final String METHOD_NAME_VALUEOF = "valueOf"; + public static final String METHOD_TYPE_VALUEOF_BOOLEAN = "(Z)Ljava/lang/String;"; + public static final String METHOD_TYPE_VALUEOF_CHAR = "(C)Ljava/lang/String;"; + public static final String METHOD_TYPE_VALUEOF_INT = "(I)Ljava/lang/String;"; + public static final String METHOD_TYPE_VALUEOF_LONG = "(J)Ljava/lang/String;"; + public static final String METHOD_TYPE_VALUEOF_FLOAT = "(F)Ljava/lang/String;"; + public static final String METHOD_TYPE_VALUEOF_DOUBLE = "(D)Ljava/lang/String;"; + public static final String METHOD_TYPE_VALUEOF_OBJECT = "(Ljava/lang/Object;)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'; - public static final char INTERNAL_TYPE_CHAR = 'C'; - public static final char INTERNAL_TYPE_SHORT = 'S'; - public static final char INTERNAL_TYPE_INT = 'I'; - public static final char INTERNAL_TYPE_LONG = 'J'; - public static final char INTERNAL_TYPE_FLOAT = 'F'; - public static final char INTERNAL_TYPE_DOUBLE = 'D'; - public static final char INTERNAL_TYPE_CLASS_START = 'L'; - public static final char INTERNAL_TYPE_CLASS_END = ';'; - public static final char INTERNAL_TYPE_ARRAY = '['; - public static final char INTERNAL_TYPE_GENERIC_VARIABLE_START = 'T'; - public static final char INTERNAL_TYPE_GENERIC_START = '<'; - public static final char INTERNAL_TYPE_GENERIC_BOUND = ':'; - public static final char INTERNAL_TYPE_GENERIC_END = '>'; + public static final String METHOD_TYPE_LENGTH = "()I"; + public static final String METHOD_NAME_APPEND = "append"; + public static final String METHOD_TYPE_STRING_VOID = "(Ljava/lang/String;)V"; + public static final String METHOD_TYPE_BOOLEAN_STRING_BUFFER = "(Z)Ljava/lang/StringBuffer;"; + public static final String METHOD_TYPE_CHAR_STRING_BUFFER = "(C)Ljava/lang/StringBuffer;"; + public static final String METHOD_TYPE_INT_STRING_BUFFER = "(I)Ljava/lang/StringBuffer;"; + public static final String METHOD_TYPE_LONG_STRING_BUFFER = "(J)Ljava/lang/StringBuffer;"; + public static final String METHOD_TYPE_FLOAT_STRING_BUFFER = "(F)Ljava/lang/StringBuffer;"; + public static final String METHOD_TYPE_DOUBLE_STRING_BUFFER = "(D)Ljava/lang/StringBuffer;"; + public static final String METHOD_TYPE_STRING_STRING_BUFFER = "(Ljava/lang/String;)Ljava/lang/StringBuffer;"; + public static final String METHOD_TYPE_OBJECT_STRING_BUFFER = "(Ljava/lang/Object;)Ljava/lang/StringBuffer;"; + public static final String METHOD_TYPE_BOOLEAN_STRING_BUILDER = "(Z)Ljava/lang/StringBuilder;"; + public static final String METHOD_TYPE_CHAR_STRING_BUILDER = "(C)Ljava/lang/StringBuilder;"; + public static final String METHOD_TYPE_INT_STRING_BUILDER = "(I)Ljava/lang/StringBuilder;"; + public static final String METHOD_TYPE_LONG_STRING_BUILDER = "(J)Ljava/lang/StringBuilder;"; + public static final String METHOD_TYPE_FLOAT_STRING_BUILDER = "(F)Ljava/lang/StringBuilder;"; + public static final String METHOD_TYPE_DOUBLE_STRING_BUILDER = "(D)Ljava/lang/StringBuilder;"; + public static final String METHOD_TYPE_STRING_STRING_BUILDER = "(Ljava/lang/String;)Ljava/lang/StringBuilder;"; + public static final String METHOD_TYPE_OBJECT_STRING_BUILDER = "(Ljava/lang/Object;)Ljava/lang/StringBuilder;"; + public static final String METHOD_NAME_TOSTRING = "toString"; + public static final String METHOD_TYPE_TOSTRING = "()Ljava/lang/String;"; + public static final String METHOD_NAME_CLONE = "clone"; + public static final String METHOD_TYPE_CLONE = "()Ljava/lang/Object;"; - public static final String EXTERNAL_TYPE_JAVA_LANG_OBJECT = "java.lang.Object"; - public static final String EXTERNAL_PACKAGE_JAVA_LANG = "java.lang."; + public static final String METHOD_NAME_VALUES = "values"; + public static final String METHOD_NAME_ORDINAL = "ordinal"; + public static final String METHOD_TYPE_ORDINAL = "()I"; - public static final String EXTERNAL_TYPE_VOID = "void"; - public static final String EXTERNAL_TYPE_BOOLEAN = "boolean"; - public static final String EXTERNAL_TYPE_BYTE = "byte"; - public static final String EXTERNAL_TYPE_CHAR = "char"; - public static final String EXTERNAL_TYPE_SHORT = "short"; - public static final String EXTERNAL_TYPE_INT = "int"; - public static final String EXTERNAL_TYPE_FLOAT = "float"; - public static final String EXTERNAL_TYPE_LONG = "long"; - public static final String EXTERNAL_TYPE_DOUBLE = "double"; - public static final String EXTERNAL_TYPE_ARRAY = "[]"; + public static final char TYPE_VOID = 'V'; + public static final char TYPE_BOOLEAN = 'Z'; + public static final char TYPE_BYTE = 'B'; + public static final char TYPE_CHAR = 'C'; + public static final char TYPE_SHORT = 'S'; + public static final char TYPE_INT = 'I'; + public static final char TYPE_LONG = 'J'; + public static final char TYPE_FLOAT = 'F'; + public static final char TYPE_DOUBLE = 'D'; + public static final char TYPE_CLASS_START = 'L'; + public static final char TYPE_CLASS_END = ';'; + public static final char TYPE_ARRAY = '['; + public static final char TYPE_GENERIC_VARIABLE_START = 'T'; + public static final char TYPE_GENERIC_START = '<'; + public static final char TYPE_GENERIC_BOUND = ':'; + public static final char TYPE_GENERIC_END = '>'; public static final int TYPICAL_CONSTANT_POOL_SIZE = 256; public static final int TYPICAL_FIELD_COUNT = 64; diff --git a/src/proguard/classfile/ClassPool.java b/src/proguard/classfile/ClassPool.java index 5439c6f..da874b5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ */ package proguard.classfile; -import proguard.classfile.util.ClassUtil; import proguard.classfile.visitor.*; import java.util.*; diff --git a/src/proguard/classfile/Clazz.java b/src/proguard/classfile/Clazz.java index 35f8a1c..a055752 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -91,6 +91,11 @@ public interface Clazz extends VisitorAccepter public String getType(int constantIndex); /** + * Returns the class name of the RefConstant at the specified index. + */ + public String getRefClassName(int constantIndex); + + /** * Returns the name of the RefConstant at the specified index. */ public String getRefName(int constantIndex); diff --git a/src/proguard/classfile/Field.java b/src/proguard/classfile/Field.java index 61bf2da..b3865a9 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/JavaConstants.java b/src/proguard/classfile/JavaConstants.java new file mode 100644 index 0000000..ad8eeca --- /dev/null +++ b/src/proguard/classfile/JavaConstants.java @@ -0,0 +1,89 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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; + +/** + * Constants used in representing a Java source file (*.java). + * + * @author Eric Lafortune + */ +public interface JavaConstants +{ + public static final String JAVA_FILE_EXTENSION = ".java"; + + public static final String CLASS_VERSION_1_0 = "1.0"; + public static final String CLASS_VERSION_1_1 = "1.1"; + public static final String CLASS_VERSION_1_2 = "1.2"; + public static final String CLASS_VERSION_1_3 = "1.3"; + public static final String CLASS_VERSION_1_4 = "1.4"; + public static final String CLASS_VERSION_1_5 = "1.5"; + public static final String CLASS_VERSION_1_6 = "1.6"; + public static final String CLASS_VERSION_1_7 = "1.7"; + public static final String CLASS_VERSION_1_8 = "1.8"; + public static final String CLASS_VERSION_1_5_ALIAS = "5"; + public static final String CLASS_VERSION_1_6_ALIAS = "6"; + public static final String CLASS_VERSION_1_7_ALIAS = "7"; + public static final String CLASS_VERSION_1_8_ALIAS = "8"; + + public static final String ACC_PUBLIC = "public"; + public static final String ACC_PRIVATE = "private"; + public static final String ACC_PROTECTED = "protected"; + public static final String ACC_STATIC = "static"; + public static final String ACC_FINAL = "final"; +// public static final String ACC_SUPER = "super"; + public static final String ACC_SYNCHRONIZED = "synchronized"; + public static final String ACC_VOLATILE = "volatile"; + public static final String ACC_TRANSIENT = "transient"; + public static final String ACC_BRIDGE = "bridge"; + public static final String ACC_VARARGS = "varargs"; + public static final String ACC_NATIVE = "native"; + public static final String ACC_INTERFACE = "interface"; + public static final String ACC_ABSTRACT = "abstract"; + public static final String ACC_STRICT = "strictfp"; + public static final String ACC_SYNTHETIC = "synthetic"; + public static final String ACC_ANNOTATION = "@"; + public static final String ACC_ENUM = "enum"; + public static final String ACC_MANDATED = "mandated"; +// public static final String ACC_CONSTRUCTOR = "constructor"; + + public static final char PACKAGE_SEPARATOR = '.'; + public static final char INNER_CLASS_SEPARATOR = '.'; + public static final char SPECIAL_CLASS_CHARACTER = '-'; + public static final char SPECIAL_MEMBER_SEPARATOR = '$'; + + public static final char METHOD_ARGUMENTS_OPEN = '('; + public static final char METHOD_ARGUMENTS_CLOSE = ')'; + public static final char METHOD_ARGUMENTS_SEPARATOR = ','; + + public static final String TYPE_JAVA_LANG_OBJECT = "java.lang.Object"; + public static final String PACKAGE_JAVA_LANG = "java.lang."; + + public static final String TYPE_VOID = "void"; + public static final String TYPE_BOOLEAN = "boolean"; + public static final String TYPE_BYTE = "byte"; + public static final String TYPE_CHAR = "char"; + public static final String TYPE_SHORT = "short"; + public static final String TYPE_INT = "int"; + public static final String TYPE_FLOAT = "float"; + public static final String TYPE_LONG = "long"; + public static final String TYPE_DOUBLE = "double"; + public static final String TYPE_ARRAY = "[]"; +}
\ No newline at end of file diff --git a/src/proguard/classfile/LibraryClass.java b/src/proguard/classfile/LibraryClass.java index 151a32a..3975677 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +74,7 @@ public class LibraryClass implements Clazz */ boolean isVisible() { - return (u2accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) != 0; + return (u2accessFlags & ClassConstants.ACC_PUBLIC) != 0; } @@ -137,6 +137,11 @@ public class LibraryClass implements Clazz } + public String getRefClassName(int constantIndex) + { + throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool"); + } + public String getRefName(int constantIndex) { throw new UnsupportedOperationException("Library class ["+thisClassName+"] doesn't store constant pool"); @@ -505,12 +510,12 @@ public class LibraryClass implements Clazz public boolean mayHaveImplementations(Method method) { return - (u2accessFlags & ClassConstants.INTERNAL_ACC_FINAL) == 0 && + (u2accessFlags & ClassConstants.ACC_FINAL) == 0 && (method == null || - ((method.getAccessFlags() & (ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_STATIC | - ClassConstants.INTERNAL_ACC_FINAL)) == 0 && - !method.getName(this).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))); + ((method.getAccessFlags() & (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC | + ClassConstants.ACC_FINAL)) == 0 && + !method.getName(this).equals(ClassConstants.METHOD_NAME_INIT))); } diff --git a/src/proguard/classfile/LibraryField.java b/src/proguard/classfile/LibraryField.java index 1c1c427..2e28d37 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 8d8d00e..1c27e1b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ import proguard.classfile.visitor.MemberVisitor; */ public abstract class LibraryMember implements Member { - private static final int ACC_VISIBLE = ClassConstants.INTERNAL_ACC_PUBLIC | - ClassConstants.INTERNAL_ACC_PROTECTED; - - public int u2accessFlags; public String name; public String descriptor; diff --git a/src/proguard/classfile/LibraryMethod.java b/src/proguard/classfile/LibraryMethod.java index ac07857..0ef7b01 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 ee2cf19..d94cd80 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 64ff50a..76eaf4f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 54bb8b1..b5d885c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -170,6 +170,18 @@ public class ProgramClass implements Clazz } + public String getRefClassName(int constantIndex) + { + try + { + return ((RefConstant)constantPool[constantIndex]).getClassName(this); + } + catch (ClassCastException ex) + { + throw ((IllegalStateException)new IllegalStateException("Expected RefConstant at index ["+constantIndex+"] in class ["+getName()+"]").initCause(ex)); + } + } + public String getRefName(int constantIndex) { try @@ -519,12 +531,12 @@ public class ProgramClass implements Clazz public boolean mayHaveImplementations(Method method) { return - (u2accessFlags & ClassConstants.INTERNAL_ACC_FINAL) == 0 && + (u2accessFlags & ClassConstants.ACC_FINAL) == 0 && (method == null || - ((method.getAccessFlags() & (ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_STATIC | - ClassConstants.INTERNAL_ACC_FINAL)) == 0 && - !method.getName(this).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))); + ((method.getAccessFlags() & (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC | + ClassConstants.ACC_FINAL)) == 0 && + !method.getName(this).equals(ClassConstants.METHOD_NAME_INIT))); } diff --git a/src/proguard/classfile/ProgramField.java b/src/proguard/classfile/ProgramField.java index 3bdfd85..c1ed101 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +20,8 @@ */ package proguard.classfile; -import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.attribute.Attribute; +import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.visitor.*; /** diff --git a/src/proguard/classfile/ProgramMember.java b/src/proguard/classfile/ProgramMember.java index 240d344..6a9b1f2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.classfile; -import proguard.classfile.attribute.*; +import proguard.classfile.attribute.Attribute; import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.visitor.MemberVisitor; diff --git a/src/proguard/classfile/ProgramMethod.java b/src/proguard/classfile/ProgramMethod.java index 26f793f..80e35e5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +20,8 @@ */ package proguard.classfile; -import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.attribute.Attribute; +import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.visitor.*; /** diff --git a/src/proguard/classfile/VisitorAccepter.java b/src/proguard/classfile/VisitorAccepter.java index 9c7a062..8fae922 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 f34a0ee..06845e0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +84,7 @@ public abstract class Attribute implements VisitorAccepter */ public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor) { - // Delegate the default invocation if the field is null anyway. + // Delegate to the default invocation if the field is null anyway. if (field == null) { accept(clazz, attributeVisitor); @@ -100,7 +100,7 @@ public abstract class Attribute implements VisitorAccepter */ public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor) { - // Delegate the default invocation if the method is null anyway. + // Delegate to the default invocation if the method is null anyway. if (method == null) { accept(clazz, (Field)null, attributeVisitor); @@ -116,7 +116,8 @@ public abstract class Attribute implements VisitorAccepter */ public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor) { - // Delegate the default invocation if the code attribute is null anyway. + // Delegate to the default invocation if the code attribute is null + // anyway. if (codeAttribute == null) { accept(clazz, method, attributeVisitor); diff --git a/src/proguard/classfile/attribute/BootstrapMethodInfo.java b/src/proguard/classfile/attribute/BootstrapMethodInfo.java index f246766..e819362 100755 --- a/src/proguard/classfile/attribute/BootstrapMethodInfo.java +++ b/src/proguard/classfile/attribute/BootstrapMethodInfo.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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/BootstrapMethodsAttribute.java b/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java index 4471a75..20b8965 100755 --- a/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java +++ b/src/proguard/classfile/attribute/BootstrapMethodsAttribute.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,9 +20,8 @@ */ package proguard.classfile.attribute; -import proguard.classfile.*; +import proguard.classfile.Clazz; import proguard.classfile.attribute.visitor.*; -import proguard.classfile.constant.visitor.ConstantVisitor; /** * This Attribute represents a bootstrap methods attribute. @@ -66,8 +65,7 @@ public class BootstrapMethodsAttribute extends Attribute /** - * Applies the given constant pool visitor to all bootstrap method info - * entries. + * Applies the given visitor to all bootstrap method info entries. */ public void bootstrapMethodEntriesAccept(Clazz clazz, BootstrapMethodInfoVisitor bootstrapMethodInfoVisitor) { @@ -81,8 +79,8 @@ public class BootstrapMethodsAttribute extends Attribute /** - * Applies the given constant pool visitor to the specified bootstrap method - * info entry. + * Applies the given visitor to the specified bootstrap method info + * entry. */ public void bootstrapMethodEntryAccept(Clazz clazz, int bootstrapMethodIndex, diff --git a/src/proguard/classfile/attribute/CodeAttribute.java b/src/proguard/classfile/attribute/CodeAttribute.java index b3d4f4c..6bcaa0a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 056e377..b90f393 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 f668063..c1920e9 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 1c2ecc4..8a31f03 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 31512e5..2bb1118 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 ff7b84a..5ae5c3d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/attribute/InnerClassesAttribute.java b/src/proguard/classfile/attribute/InnerClassesAttribute.java index b08d104..f0c9e1e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 87b9de4..7a1eb67 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/attribute/LineNumberInfo.java b/src/proguard/classfile/attribute/LineNumberInfo.java index 1bcacef..0dd527c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 c217119..7bd3e00 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/attribute/LocalVariableInfo.java b/src/proguard/classfile/attribute/LocalVariableInfo.java index 00bbd50..88035ce 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -76,6 +76,24 @@ public class LocalVariableInfo implements VisitorAccepter, Comparable /** + * Returns the name. + */ + public String getName(Clazz clazz) + { + return clazz.getString(u2nameIndex); + } + + + /** + * Returns the descriptor. + */ + public String getDescriptor(Clazz clazz) + { + return clazz.getString(u2descriptorIndex); + } + + + /** * Lets the referenced class accept the given visitor. */ public void referencedClassAccept(ClassVisitor classVisitor) diff --git a/src/proguard/classfile/attribute/LocalVariableTableAttribute.java b/src/proguard/classfile/attribute/LocalVariableTableAttribute.java index 9e081c0..a48e890 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 15b9d24..c0fc405 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,24 @@ public class LocalVariableTypeInfo implements VisitorAccepter, Comparable /** + * Returns the name. + */ + public String getName(Clazz clazz) + { + return clazz.getString(u2nameIndex); + } + + + /** + * Returns the signature. + */ + public String getSignature(Clazz clazz) + { + return clazz.getString(u2signatureIndex); + } + + + /** * Applies the given visitor to all referenced classes. */ public void referencedClassesAccept(ClassVisitor classVisitor) diff --git a/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java b/src/proguard/classfile/attribute/LocalVariableTypeTableAttribute.java index dda24fb..62643bc 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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/MethodParametersAttribute.java b/src/proguard/classfile/attribute/MethodParametersAttribute.java new file mode 100644 index 0000000..5e832d2 --- /dev/null +++ b/src/proguard/classfile/attribute/MethodParametersAttribute.java @@ -0,0 +1,80 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.*; + +/** + * This Attribute represents a method parameters attribute. + * + * @author Eric Lafortune + */ +public class MethodParametersAttribute extends Attribute +{ + public int u1parametersCount; + public ParameterInfo[] parameters; + + + /** + * Creates an uninitialized MethodParametersAttribute. + */ + public MethodParametersAttribute() + { + } + + + /** + * Creates an initialized MethodParametersAttribute. + */ + public MethodParametersAttribute(int u2attributeNameIndex, + int u1parametersCount, + ParameterInfo[] parameters) + { + super(u2attributeNameIndex); + + this.u1parametersCount = u1parametersCount; + this.parameters = parameters; + } + + + // Implementations for Attribute. + + public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor) + { + attributeVisitor.visitMethodParametersAttribute(clazz, method, this); + } + + + /** + * Applies the given visitor to all parameters. + */ + public void parametersAccept(Clazz clazz, Method method, ParameterInfoVisitor parameterInfoVisitor) + { + // Loop over all parameters. + for (int index = 0; index < u1parametersCount; index++) + { + // We don't need double dispatching here, since there is only one + // type of ParameterInfo. + parameterInfoVisitor.visitParameterInfo(clazz, method, index, parameters[index]); + } + } +} diff --git a/src/proguard/classfile/attribute/ParameterInfo.java b/src/proguard/classfile/attribute/ParameterInfo.java new file mode 100644 index 0000000..dac5e1a --- /dev/null +++ b/src/proguard/classfile/attribute/ParameterInfo.java @@ -0,0 +1,81 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.*; + +/** + * Representation of a parameter, as defined in a method parameters + * attribute. + * + * @author Eric Lafortune + */ +public class ParameterInfo implements VisitorAccepter +{ + public int u2nameIndex; + public int u2accessFlags; + + /** + * An extra field in which visitors can store information. + */ + public Object visitorInfo; + + + /** + * Creates an uninitialized ParameterInfo. + */ + public ParameterInfo() + { + } + + + /** + * Creates an initialized ParameterInfo. + */ + public ParameterInfo(int u2nameIndex, + int u2accessFlags) + { + this.u2nameIndex = u2nameIndex; + this.u2accessFlags = u2accessFlags; + } + + + /** + * Returns the parameter name. + */ + public String getName(Clazz clazz) + { + return clazz.getString(u2nameIndex); + } + + + // Implementations for VisitorAccepter. + + public Object getVisitorInfo() + { + return visitorInfo; + } + + public void setVisitorInfo(Object visitorInfo) + { + this.visitorInfo = visitorInfo; + } +} diff --git a/src/proguard/classfile/attribute/SignatureAttribute.java b/src/proguard/classfile/attribute/SignatureAttribute.java index 86f95b8..120fa96 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 +63,15 @@ public class SignatureAttribute extends Attribute /** + * Returns the signature. + */ + public String getSignature(Clazz clazz) + { + return clazz.getString(u2signatureIndex); + } + + + /** * Lets the Clazz objects referenced in the signature string accept the * given visitor. */ diff --git a/src/proguard/classfile/attribute/SourceDirAttribute.java b/src/proguard/classfile/attribute/SourceDirAttribute.java index faa1c79..100c840 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 4abac17..e10b784 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 0135330..a308545 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 182a9e8..f928f25 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,15 +32,17 @@ import proguard.classfile.attribute.visitor.AttributeVisitor; public class UnknownAttribute extends Attribute { public final int u4attributeLength; - public byte[] info; + public byte[] info; /** - * Creates an uninitialized UnknownAttribute with the given length. + * Creates an uninitialized UnknownAttribute with the specified name and + * length. */ - public UnknownAttribute(int attributeLength) + public UnknownAttribute(int u2attributeNameIndex, + int attributeLength) { - u4attributeLength = attributeLength; + this(u2attributeNameIndex, attributeLength, null); } diff --git a/src/proguard/classfile/attribute/annotation/Annotation.java b/src/proguard/classfile/attribute/annotation/Annotation.java index b2f18d5..3e24a9e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 b8f29cc..1b06e82 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 8354f5d..1e6365c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/AnnotationsAttribute.java index a936ff4..dcb7cf6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.classfile.attribute.annotation; import proguard.classfile.*; -import proguard.classfile.attribute.Attribute; +import proguard.classfile.attribute.*; import proguard.classfile.attribute.annotation.visitor.AnnotationVisitor; /** @@ -44,7 +44,7 @@ public abstract class AnnotationsAttribute extends Attribute /** - * Creates an initialized AnnotationsAttribute. + * Creates an initialized AnnotationsAttribute. */ protected AnnotationsAttribute(int u2attributeNameIndex, int u2annotationsCount, @@ -97,4 +97,18 @@ public abstract class AnnotationsAttribute extends Attribute annotationVisitor.visitAnnotation(clazz, method, annotations[index]); } } + + + /** + * Applies the given visitor to all code attribute annotations. + */ + public void annotationsAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, AnnotationVisitor annotationVisitor) + { + for (int index = 0; index < u2annotationsCount; index++) + { + // We don't need double dispatching here, since there is only one + // type of Annotation. + annotationVisitor.visitAnnotation(clazz, method, codeAttribute, annotations[index]); + } + } } diff --git a/src/proguard/classfile/attribute/annotation/ArrayElementValue.java b/src/proguard/classfile/attribute/annotation/ArrayElementValue.java index 0aab49b..4d814c0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/attribute/annotation/ClassElementValue.java b/src/proguard/classfile/attribute/annotation/ClassElementValue.java index ffeaf71..0e5de1e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 +63,15 @@ public class ClassElementValue extends ElementValue /** + * Returns the class info name. + */ + public String getClassName(Clazz clazz) + { + return clazz.getString(u2classInfoIndex); + } + + + /** * Applies the given visitor to all referenced classes. */ public void referencedClassesAccept(ClassVisitor classVisitor) diff --git a/src/proguard/classfile/attribute/annotation/ConstantElementValue.java b/src/proguard/classfile/attribute/annotation/ConstantElementValue.java index 8be4329..5ff51db 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/attribute/annotation/ElementValue.java b/src/proguard/classfile/attribute/annotation/ElementValue.java index 19a7198..9c0f2c9 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java b/src/proguard/classfile/attribute/annotation/EnumConstantElementValue.java index cd0f2f9..1105100 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/ParameterAnnotationsAttribute.java index ddaa3a6..4b0cb1c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,13 +25,13 @@ import proguard.classfile.attribute.Attribute; import proguard.classfile.attribute.annotation.visitor.AnnotationVisitor; /** - * This Attribute represents a runtime parameter annotations attribute. + * This Attribute represents a parameter annotations attribute. * * @author Eric Lafortune */ public abstract class ParameterAnnotationsAttribute extends Attribute { - public int u2parametersCount; + public int u1parametersCount; public int[] u2parameterAnnotationsCount; public Annotation[][] parameterAnnotations; @@ -48,13 +48,13 @@ public abstract class ParameterAnnotationsAttribute extends Attribute * Creates an initialized ParameterAnnotationsAttribute. */ protected ParameterAnnotationsAttribute(int u2attributeNameIndex, - int u2parametersCount, + int u1parametersCount, int[] u2parameterAnnotationsCount, Annotation[][] parameterAnnotations) { super(u2attributeNameIndex); - this.u2parametersCount = u2parametersCount; + this.u1parametersCount = u1parametersCount; this.u2parameterAnnotationsCount = u2parameterAnnotationsCount; this.parameterAnnotations = parameterAnnotations; } @@ -66,7 +66,7 @@ public abstract class ParameterAnnotationsAttribute extends Attribute public void annotationsAccept(Clazz clazz, Method method, AnnotationVisitor annotationVisitor) { // Loop over all parameters. - for (int parameterIndex = 0; parameterIndex < u2parametersCount; parameterIndex++) + for (int parameterIndex = 0; parameterIndex < u1parametersCount; parameterIndex++) { int annotationsCount = u2parameterAnnotationsCount[parameterIndex]; Annotation[] annotations = parameterAnnotations[parameterIndex]; diff --git a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleAnnotationsAttribute.java index deda8a5..84d9d61 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 2fcae88..0a5e1d7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,12 +42,12 @@ public class RuntimeInvisibleParameterAnnotationsAttribute extends ParameterAnno * Creates an initialized RuntimeInvisibleParameterAnnotationsAttribute. */ public RuntimeInvisibleParameterAnnotationsAttribute(int u2attributeNameIndex, - int u2parametersCount, + int u1parametersCount, int[] u2parameterAnnotationsCount, Annotation[][] parameterAnnotations) { super(u2attributeNameIndex, - u2parametersCount, + u1parametersCount, u2parameterAnnotationsCount, parameterAnnotations); } diff --git a/src/proguard/classfile/attribute/annotation/RuntimeInvisibleTypeAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleTypeAnnotationsAttribute.java new file mode 100644 index 0000000..2e1ca95 --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/RuntimeInvisibleTypeAnnotationsAttribute.java @@ -0,0 +1,77 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.visitor.AttributeVisitor; + +/** + * This Attribute represents a runtime invisible type annotations attribute. + * + * @author Eric Lafortune + */ +public class RuntimeInvisibleTypeAnnotationsAttribute extends TypeAnnotationsAttribute +{ + /** + * Creates an uninitialized RuntimeInvisibleTypeAnnotationsAttribute. + */ + public RuntimeInvisibleTypeAnnotationsAttribute() + { + } + + + /** + * Creates an initialized RuntimeInvisibleTypeAnnotationsAttribute. + */ + public RuntimeInvisibleTypeAnnotationsAttribute(int u2attributeNameIndex, + int u2annotationsCount, + TypeAnnotation[] annotations) + { + super(u2attributeNameIndex, u2annotationsCount, annotations); + } + + + // Implementations for Attribute. + + public void accept(Clazz clazz, AttributeVisitor attributeVisitor) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, this); + } + + + public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, this); + } + + + public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, this); + } + + + public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeVisibleAnnotationsAttribute.java index da94f0c..89acf04 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 caa6830..cc273c2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,12 +42,12 @@ public class RuntimeVisibleParameterAnnotationsAttribute extends ParameterAnnota * Creates an initialized RuntimeVisibleParameterAnnotationsAttribute. */ public RuntimeVisibleParameterAnnotationsAttribute(int u2attributeNameIndex, - int u2parametersCount, + int u1parametersCount, int[] u2parameterAnnotationsCount, Annotation[][] parameterAnnotations) { super(u2attributeNameIndex, - u2parametersCount, + u1parametersCount, u2parameterAnnotationsCount, parameterAnnotations); } diff --git a/src/proguard/classfile/attribute/annotation/RuntimeVisibleTypeAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/RuntimeVisibleTypeAnnotationsAttribute.java new file mode 100644 index 0000000..084827a --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/RuntimeVisibleTypeAnnotationsAttribute.java @@ -0,0 +1,77 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.visitor.AttributeVisitor; + +/** + * This Attribute represents a runtime visible type annotations attribute. + * + * @author Eric Lafortune + */ +public class RuntimeVisibleTypeAnnotationsAttribute extends TypeAnnotationsAttribute +{ + /** + * Creates an uninitialized RuntimeVisibleTypeAnnotationsAttribute. + */ + public RuntimeVisibleTypeAnnotationsAttribute() + { + } + + + /** + * Creates an initialized RuntimeVisibleTypeAnnotationsAttribute. + */ + public RuntimeVisibleTypeAnnotationsAttribute(int u2attributeNameIndex, + int u2annotationsCount, + TypeAnnotation[] annotations) + { + super(u2attributeNameIndex, u2annotationsCount, annotations); + } + + + // Implementations for Attribute. + + public void accept(Clazz clazz, AttributeVisitor attributeVisitor) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, this); + } + + + public void accept(Clazz clazz, Field field, AttributeVisitor attributeVisitor) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, this); + } + + + public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, this); + } + + + public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, AttributeVisitor attributeVisitor) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/TypeAnnotation.java b/src/proguard/classfile/attribute/annotation/TypeAnnotation.java new file mode 100644 index 0000000..86e4ddf --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/TypeAnnotation.java @@ -0,0 +1,162 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.annotation.target.TargetInfo; +import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor; +import proguard.classfile.attribute.annotation.visitor.*; + +/** + * Representation of a type annotation. + * + * @author Eric Lafortune + */ +public class TypeAnnotation extends Annotation +{ + public TargetInfo targetInfo; + public TypePathInfo[] typePath; + + + /** + * Creates an uninitialized TypeAnnotation. + */ + public TypeAnnotation() + { + } + + + /** + * Creates an initialized TypeAnnotation. + */ + public TypeAnnotation(int u2typeIndex, + int u2elementValuesCount, + ElementValue[] elementValues, + TargetInfo targetInfo, + TypePathInfo[] typePath) + { + super(u2typeIndex, u2elementValuesCount, elementValues); + + this.targetInfo = targetInfo; + this.typePath = typePath; + } + + + /** + * Applies the given visitor to the target info. + */ + public void targetInfoAccept(Clazz clazz, TargetInfoVisitor targetInfoVisitor) + { + // We don't need double dispatching here, since there is only one + // type of TypePathInfo. + targetInfo.accept(clazz, this, targetInfoVisitor); + } + + + /** + * Applies the given visitor to the target info. + */ + public void targetInfoAccept(Clazz clazz, Field field, TargetInfoVisitor targetInfoVisitor) + { + // We don't need double dispatching here, since there is only one + // type of TypePathInfo. + targetInfo.accept(clazz, field, this, targetInfoVisitor); + } + + + /** + * Applies the given visitor to the target info. + */ + public void targetInfoAccept(Clazz clazz, Method method, TargetInfoVisitor targetInfoVisitor) + { + // We don't need double dispatching here, since there is only one + // type of TypePathInfo. + targetInfo.accept(clazz, method, this, targetInfoVisitor); + } + + + /** + * Applies the given visitor to the target info. + */ + public void targetInfoAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, TargetInfoVisitor targetInfoVisitor) + { + // We don't need double dispatching here, since there is only one + // type of TypePathInfo. + targetInfo.accept(clazz, method, codeAttribute, this, targetInfoVisitor); + } + + + /** + * Applies the given visitor to all type path elements. + */ + public void typePathInfosAccept(Clazz clazz, TypePathInfoVisitor typePathVisitor) + { + for (int index = 0; index < typePath.length; index++) + { + // We don't need double dispatching here, since there is only one + // type of TypePathInfo. + typePathVisitor.visitTypePathInfo(clazz, this, typePath[index]); + } + } + + + /** + * Applies the given visitor to all type path elements. + */ + public void typePathInfosAccept(Clazz clazz, Field field, TypePathInfoVisitor typePathVisitor) + { + for (int index = 0; index < typePath.length; index++) + { + // We don't need double dispatching here, since there is only one + // type of TypePathInfo. + typePathVisitor.visitTypePathInfo(clazz, field, this, typePath[index]); + } + } + + + /** + * Applies the given visitor to all type path elements. + */ + public void typePathInfosAccept(Clazz clazz, Method method, TypePathInfoVisitor typePathVisitor) + { + for (int index = 0; index < typePath.length; index++) + { + // We don't need double dispatching here, since there is only one + // type of TypePathInfo. + typePathVisitor.visitTypePathInfo(clazz, method, this, typePath[index]); + } + } + + + /** + * Applies the given visitor to all type path elements. + */ + public void typePathInfosAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypePathInfoVisitor typePathVisitor) + { + for (int index = 0; index < typePath.length; index++) + { + // We don't need double dispatching here, since there is only one + // type of TypePathInfo. + typePathVisitor.visitTypePathInfo(clazz, method, codeAttribute, typeAnnotation, typePath[index]); + } + } +} diff --git a/src/proguard/classfile/attribute/annotation/TypeAnnotationsAttribute.java b/src/proguard/classfile/attribute/annotation/TypeAnnotationsAttribute.java new file mode 100644 index 0000000..7606e05 --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/TypeAnnotationsAttribute.java @@ -0,0 +1,98 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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; + +import proguard.classfile.*; +import proguard.classfile.attribute.annotation.visitor.*; + +/** + * This Attribute represents a type annotations attribute. + * + * @author Eric Lafortune + */ +public abstract class TypeAnnotationsAttribute extends AnnotationsAttribute +{ + /** + * Creates an uninitialized TypeAnnotationsAttribute. + */ + protected TypeAnnotationsAttribute() + { + } + + + /** + * Creates an initialized TypeAnnotationsAttribute. + */ + protected TypeAnnotationsAttribute(int u2attributeNameIndex, + int u2annotationsCount, + TypeAnnotation[] annotations) + { + super(u2attributeNameIndex, u2annotationsCount, annotations); + } + + + /** + * Applies the given visitor to all class annotations. + */ + public void typeAnnotationsAccept(Clazz clazz, TypeAnnotationVisitor typeAnnotationVisitor) + { + TypeAnnotation[] annotations = (TypeAnnotation[])this.annotations; + + for (int index = 0; index < u2annotationsCount; index++) + { + // We don't need double dispatching here, since there is only one + // type of Annotation. + typeAnnotationVisitor.visitTypeAnnotation(clazz, annotations[index]); + } + } + + + /** + * Applies the given visitor to all field annotations. + */ + public void typeAnnotationsAccept(Clazz clazz, Field field, TypeAnnotationVisitor typeAnnotationVisitor) + { + TypeAnnotation[] annotations = (TypeAnnotation[])this.annotations; + + for (int index = 0; index < u2annotationsCount; index++) + { + // We don't need double dispatching here, since there is only one + // type of Annotation. + typeAnnotationVisitor.visitTypeAnnotation(clazz, field, annotations[index]); + } + } + + + /** + * Applies the given visitor to all method annotations. + */ + public void typeAnnotationsAccept(Clazz clazz, Method method, TypeAnnotationVisitor typeAnnotationVisitor) + { + TypeAnnotation[] annotations = (TypeAnnotation[])this.annotations; + + for (int index = 0; index < u2annotationsCount; index++) + { + // We don't need double dispatching here, since there is only one + // type of Annotation. + typeAnnotationVisitor.visitTypeAnnotation(clazz, method, annotations[index]); + } + } +} diff --git a/src/proguard/classfile/attribute/annotation/TypePathInfo.java b/src/proguard/classfile/attribute/annotation/TypePathInfo.java new file mode 100644 index 0000000..9b40f7c --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/TypePathInfo.java @@ -0,0 +1,50 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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; + +/** + * Representation of a path element in a type annotation. + * + * @author Eric Lafortune + */ +public class TypePathInfo +{ + public int u1typePathKind; + public int u1typeArgumentIndex; + + + /** + * Creates an uninitialized TypePathInfo. + */ + public TypePathInfo() + { + } + + + /** + * Creates an initialized TypePathInfo. + */ + public TypePathInfo(int u1typePathKind, int u1typeArgumentIndex) + { + this.u1typePathKind = u1typePathKind; + this.u1typeArgumentIndex = u1typeArgumentIndex; + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/CatchTargetInfo.java b/src/proguard/classfile/attribute/annotation/target/CatchTargetInfo.java new file mode 100644 index 0000000..9421b9c --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/CatchTargetInfo.java @@ -0,0 +1,82 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor; + +/** + * Representation of a 'catch' annotation target. + * + * @author Eric Lafortune + */ +public class CatchTargetInfo extends TargetInfo +{ + public int u2exceptionTableIndex; + + + /** + * Creates an uninitialized CatchTargetInfo. + */ + public CatchTargetInfo() + { + } + + + /** + * Creates a partially initialized CatchTargetInfo. + */ + public CatchTargetInfo(byte u1targetType) + { + super(u1targetType); + } + + + /** + * Creates an initialized CatchTargetInfo. + */ + protected CatchTargetInfo(byte u1targetType, + int u2exceptionTableIndex) + { + super(u1targetType); + + this.u2exceptionTableIndex = u2exceptionTableIndex; + } + + + // Implementations for TargetInfo. + + /** + * Lets the visitor visit, with Method and CodeAttribute null. + */ + public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitCatchTargetInfo(clazz, null, null, typeAnnotation, this); + } + + + public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitCatchTargetInfo(clazz, method, codeAttribute, typeAnnotation, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/EmptyTargetInfo.java b/src/proguard/classfile/attribute/annotation/target/EmptyTargetInfo.java new file mode 100644 index 0000000..fb0d794 --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/EmptyTargetInfo.java @@ -0,0 +1,72 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +import proguard.classfile.*; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor; + +/** + * Representation of an empty annotation target. + * + * @author Eric Lafortune + */ +public class EmptyTargetInfo extends TargetInfo +{ + /** + * Creates an uninitialized EmptyTargetInfo. + */ + public EmptyTargetInfo() + { + } + + + /** + * Creates an initialized EmptyTargetInfo. + */ + public EmptyTargetInfo(byte u1targetType) + { + super(u1targetType); + } + + + // Implementations for TargetInfo. + + /** + * Lets the visitor visit, with Field null. + */ + public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitEmptyTargetInfo(clazz, (Field)null, typeAnnotation, this); + } + + + public void accept(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitEmptyTargetInfo(clazz, field, typeAnnotation, this); + } + + + public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitEmptyTargetInfo(clazz, method, typeAnnotation, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/FormalParameterTargetInfo.java b/src/proguard/classfile/attribute/annotation/target/FormalParameterTargetInfo.java new file mode 100644 index 0000000..04bd9c5 --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/FormalParameterTargetInfo.java @@ -0,0 +1,81 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +import proguard.classfile.*; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor; + +/** + * Representation of a formal parameter annotation target. + * + * @author Eric Lafortune + */ +public class FormalParameterTargetInfo extends TargetInfo +{ + public int u1formalParameterIndex; + + + /** + * Creates an uninitialized FormalParameterTargetInfo. + */ + public FormalParameterTargetInfo() + { + } + + + /** + * Creates a partially initialized FormalParameterTargetInfo. + */ + public FormalParameterTargetInfo(byte u1targetType) + { + super(u1targetType); + } + + + /** + * Creates an initialized FormalParameterTargetInfo. + */ + public FormalParameterTargetInfo(byte u1targetType, + int u1formalParameterIndex) + { + super(u1targetType); + + this.u1formalParameterIndex = u1formalParameterIndex; + } + + + // Implementations for TargetInfo. + + /** + * Lets the visitor visit, with Method null. + */ + public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitFormalParameterTargetInfo(clazz, null, typeAnnotation, this); + } + + + public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitFormalParameterTargetInfo(clazz, method, typeAnnotation, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetElement.java b/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetElement.java new file mode 100644 index 0000000..bcf41dc --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetElement.java @@ -0,0 +1,53 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +/** + * Representation of an local variable target table entry. + * + * @author Eric Lafortune + */ +public class LocalVariableTargetElement +{ + public int u2startPC; + public int u2length; + public int u2index; + + /** + * Creates an uninitialized LocalVariableTargetElement. + */ + public LocalVariableTargetElement() + { + } + + + /** + * Creates an initialized LocalVariableTargetElement. + */ + public LocalVariableTargetElement(int u2startPC, + int u2length, + int u2index) + { + this.u2startPC = u2startPC; + this.u2length = u2length; + this.u2index = u2index; + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetInfo.java b/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetInfo.java new file mode 100644 index 0000000..dd9246c --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/LocalVariableTargetInfo.java @@ -0,0 +1,99 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.visitor.*; + +/** + * Representation of a local variable annotation target. + * + * @author Eric Lafortune + */ +public class LocalVariableTargetInfo extends TargetInfo +{ + public int u2tableLength; + public LocalVariableTargetElement[] table; + + + /** + * Creates an uninitialized LocalVariableTargetInfo. + */ + public LocalVariableTargetInfo() + { + } + + + /** + * Creates a partially initialized LocalVariableTargetInfo. + */ + public LocalVariableTargetInfo(byte u1targetType) + { + super(u1targetType); + } + + + /** + * Creates an initialized LocalVariableTargetInfo. + */ + protected LocalVariableTargetInfo(byte u1targetType, + int u2tableLength, + LocalVariableTargetElement[] table) + { + super(u1targetType); + + this.u2tableLength = u2tableLength; + this.table = table; + } + + + /** + * Applies the given visitor to all target elements. + */ + public void targetElementsAccept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetElementVisitor localVariableTargetElementVisitor) + { + for (int index = 0; index < u2tableLength; index++) + { + // We don't need double dispatching here, since there is only one + // type of TypePathInfo. + localVariableTargetElementVisitor.visitLocalVariableTargetElement(clazz, method, codeAttribute, typeAnnotation, this, table[index]); + } + } + + + // Implementations for TargetInfo. + + /** + * Lets the visitor visit, with Method and CodeAttribute null. + */ + public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitLocalVariableTargetInfo(clazz, null, null, typeAnnotation, this); + } + + + public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitLocalVariableTargetInfo(clazz, method, codeAttribute, typeAnnotation, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/OffsetTargetInfo.java b/src/proguard/classfile/attribute/annotation/target/OffsetTargetInfo.java new file mode 100644 index 0000000..312046b --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/OffsetTargetInfo.java @@ -0,0 +1,82 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor; + +/** + * Representation of an offset annotation target. + * + * @author Eric Lafortune + */ +public class OffsetTargetInfo extends TargetInfo +{ + public int u2offset; + + + /** + * Creates an uninitialized OffsetTargetInfo. + */ + public OffsetTargetInfo() + { + } + + + /** + * Creates a partially initialized OffsetTargetInfo. + */ + public OffsetTargetInfo(byte u1targetType) + { + super(u1targetType); + } + + + /** + * Creates an initialized OffsetTargetInfo. + */ + protected OffsetTargetInfo(byte u1targetType, + int u2offset) + { + super(u1targetType); + + this.u2offset = u2offset; + } + + + // Implementations for TargetInfo. + + /** + * Lets the visitor visit, with Method and CodeAttribute null. + */ + public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitOffsetTargetInfo(clazz, null, null, typeAnnotation, this); + } + + + public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitOffsetTargetInfo(clazz, method, codeAttribute, typeAnnotation, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/SuperTypeTargetInfo.java b/src/proguard/classfile/attribute/annotation/target/SuperTypeTargetInfo.java new file mode 100644 index 0000000..0db7ea4 --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/SuperTypeTargetInfo.java @@ -0,0 +1,72 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +import proguard.classfile.Clazz; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor; + +/** + * Representation of a super type annotation target. + * + * @author Eric Lafortune + */ +public class SuperTypeTargetInfo extends TargetInfo +{ + public int u2superTypeIndex; + + + /** + * Creates an uninitialized SuperTypeTargetInfo. + */ + public SuperTypeTargetInfo() + { + } + + + /** + * Creates a partially initialized SuperTypeTargetInfo. + */ + public SuperTypeTargetInfo(byte u1targetType) + { + super(u1targetType); + } + + + /** + * Creates an initialized SuperTypeTargetInfo. + */ + public SuperTypeTargetInfo(byte u1targetType, + int u2superTypeIndex) + { + super(u1targetType); + + this.u2superTypeIndex = u2superTypeIndex; + } + + + // Implementations for TargetInfo. + + public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitSuperTypeTargetInfo(clazz, typeAnnotation, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/TargetInfo.java b/src/proguard/classfile/attribute/annotation/target/TargetInfo.java new file mode 100644 index 0000000..efee2e2 --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/TargetInfo.java @@ -0,0 +1,97 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor; + +/** + * Representation of an annotation target. + * + * @author Eric Lafortune + */ +public abstract class TargetInfo +{ + public byte u1targetType; + + + /** + * Creates an uninitialized TargetInfo. + */ + protected TargetInfo() + { + } + + + /** + * Creates an initialized TargetInfo. + */ + protected TargetInfo(byte u1targetType) + { + this.u1targetType = u1targetType; + } + + + /** + * Returns the type of the target. + */ + public byte getTargetType() + { + return u1targetType; + } + + + // Methods to be implemented by extensions. + + /** + * Accepts the given visitor, in the context of a type annotation on a class. + */ + public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + throw new UnsupportedOperationException("Unsupported type annotation [0x"+Integer.toHexString(u1targetType)+"] on a class"); + } + + /** + * Accepts the given visitor, in the context of a type annotation on a field. + */ + public void accept(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + throw new UnsupportedOperationException("Unsupported type annotation [0x"+Integer.toHexString(u1targetType)+"] on a field"); + } + + /** + * Accepts the given visitor, in the context of a type annotation on a method. + */ + public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + throw new UnsupportedOperationException("Unsupported type annotation [0x"+Integer.toHexString(u1targetType)+"] on a method"); + } + + /** + * Accepts the given visitor, in the context of a type annotation code. + */ + public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + throw new UnsupportedOperationException("Unsupported type annotation [0x"+Integer.toHexString(u1targetType)+"] on code"); + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/ThrowsTargetInfo.java b/src/proguard/classfile/attribute/annotation/target/ThrowsTargetInfo.java new file mode 100644 index 0000000..d5b2db7 --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/ThrowsTargetInfo.java @@ -0,0 +1,81 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +import proguard.classfile.*; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor; + +/** + * Representation of a 'throws' annotation target. + * + * @author Eric Lafortune + */ +public class ThrowsTargetInfo extends TargetInfo +{ + public int u2throwsTypeIndex; + + + /** + * Creates an uninitialized ThrowsTargetInfo. + */ + public ThrowsTargetInfo() + { + } + + + /** + * Creates a partially initialized ThrowsTargetInfo. + */ + public ThrowsTargetInfo(byte u1targetType) + { + super(u1targetType); + } + + + /** + * Creates an initialized ThrowsTargetInfo. + */ + public ThrowsTargetInfo(byte u1targetType, + int u2throwsTypeIndex) + { + super(u1targetType); + + this.u2throwsTypeIndex = u2throwsTypeIndex; + } + + + // Implementations for TargetInfo. + + /** + * Lets the visitor visit, with Method null. + */ + public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitThrowsTargetInfo(clazz, null, typeAnnotation, this); + } + + + public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitThrowsTargetInfo(clazz, method, typeAnnotation, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/TypeArgumentTargetInfo.java b/src/proguard/classfile/attribute/annotation/target/TypeArgumentTargetInfo.java new file mode 100644 index 0000000..4aef72e --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/TypeArgumentTargetInfo.java @@ -0,0 +1,85 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor; + +/** + * Representation of an offset annotation target. + * + * @author Eric Lafortune + */ +public class TypeArgumentTargetInfo extends TargetInfo +{ + public int u2offset; + public int u1typeArgumentIndex; + + + /** + * Creates an uninitialized TypeArgumentTargetInfo. + */ + public TypeArgumentTargetInfo() + { + } + + + /** + * Creates a partially initialized TypeArgumentTargetInfo. + */ + public TypeArgumentTargetInfo(byte u1targetType) + { + super(u1targetType); + } + + + /** + * Creates an initialized TypeArgumentTargetInfo. + */ + protected TypeArgumentTargetInfo(byte u1targetType, + int u2offset, + int u1typeArgumentIndex) + { + super(u1targetType); + + this.u2offset = u2offset; + this.u1typeArgumentIndex = u1typeArgumentIndex; + } + + + // Implementations for TargetInfo. + + /** + * Lets the visitor visit, with Method and CodeAttribute null. + */ + public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitTypeArgumentTargetInfo(clazz, null, null, typeAnnotation, this); + } + + + public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitTypeArgumentTargetInfo(clazz, method, codeAttribute, typeAnnotation, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/TypeParameterBoundTargetInfo.java b/src/proguard/classfile/attribute/annotation/target/TypeParameterBoundTargetInfo.java new file mode 100644 index 0000000..0f485ee --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/TypeParameterBoundTargetInfo.java @@ -0,0 +1,87 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +import proguard.classfile.*; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor; + +/** + * Representation of a type parameter bound annotation target. + * + * @author Eric Lafortune + */ +public class TypeParameterBoundTargetInfo extends TargetInfo +{ + public int u1typeParameterIndex; + public int u1boundIndex; + + + /** + * Creates an uninitialized TypeParameterBoundTargetInfo. + */ + public TypeParameterBoundTargetInfo() + { + } + + + /** + * Creates a partially initialized TypeParameterBoundTargetInfo. + */ + public TypeParameterBoundTargetInfo(byte u1targetType) + { + super(u1targetType); + } + + + /** + * Creates an initialized TypeParameterBoundTargetInfo. + */ + public TypeParameterBoundTargetInfo(byte u1targetType, + int u1typeParameterIndex, + int u1boundIndex) + { + super(u1targetType); + + this.u1typeParameterIndex = u1typeParameterIndex; + this.u1boundIndex = u1boundIndex; + } + + + // Implementations for TargetInfo. + + public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitTypeParameterBoundTargetInfo(clazz, typeAnnotation, this); + } + + + public void accept(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitTypeParameterBoundTargetInfo(clazz, field, typeAnnotation, this); + } + + + public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitTypeParameterBoundTargetInfo(clazz, method, typeAnnotation, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/TypeParameterTargetInfo.java b/src/proguard/classfile/attribute/annotation/target/TypeParameterTargetInfo.java new file mode 100644 index 0000000..3150a26 --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/TypeParameterTargetInfo.java @@ -0,0 +1,79 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.visitor.TargetInfoVisitor; + +/** + * Representation of a type parameter annotation target. + * + * @author Eric Lafortune + */ +public class TypeParameterTargetInfo extends TargetInfo +{ + public int u1typeParameterIndex; + + + /** + * Creates an uninitialized TypeParameterTargetInfo. + */ + public TypeParameterTargetInfo() + { + } + + + /** + * Creates a partially initialized TypeParameterTargetInfo. + */ + public TypeParameterTargetInfo(byte u1targetType) + { + super(u1targetType); + } + + + /** + * Creates an initialized TypeParameterTargetInfo. + */ + public TypeParameterTargetInfo(byte u1targetType, + int u1typeParameterIndex) + { + super(u1targetType); + + this.u1typeParameterIndex = u1typeParameterIndex; + } + + + // Implementations for TargetInfo. + + public void accept(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitTypeParameterTargetInfo(clazz, typeAnnotation, this); + } + + + public void accept(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TargetInfoVisitor targetInfoVisitor) + { + targetInfoVisitor.visitTypeParameterTargetInfo(clazz, method, typeAnnotation, this); + } +} diff --git a/src/proguard/classfile/attribute/annotation/target/visitor/LocalVariableTargetElementVisitor.java b/src/proguard/classfile/attribute/annotation/target/visitor/LocalVariableTargetElementVisitor.java new file mode 100644 index 0000000..62fe148 --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/visitor/LocalVariableTargetElementVisitor.java @@ -0,0 +1,37 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target.visitor; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.annotation.TypeAnnotation; +import proguard.classfile.attribute.annotation.target.*; + +/** + * This interface specifies the methods for a visitor of LocalVariableTargetElement + * instances. + * + * @author Eric Lafortune + */ +public interface LocalVariableTargetElementVisitor +{ + public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement); +} diff --git a/src/proguard/classfile/attribute/annotation/target/visitor/TargetInfoVisitor.java b/src/proguard/classfile/attribute/annotation/target/visitor/TargetInfoVisitor.java new file mode 100644 index 0000000..33e7d32 --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/target/visitor/TargetInfoVisitor.java @@ -0,0 +1,50 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.target.visitor; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.target.*; + +/** + * This interface specifies the methods for a visitor of <code>TargetInfo</code> + * objects. + * + * @author Eric Lafortune + */ +public interface TargetInfoVisitor +{ + public void visitTypeParameterTargetInfo( Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo); + public void visitTypeParameterTargetInfo( Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo); + public void visitSuperTypeTargetInfo( Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo); + public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo); + public void visitTypeParameterBoundTargetInfo(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo); + public void visitTypeParameterBoundTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo); + public void visitEmptyTargetInfo( Clazz clazz, Field field, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo); + public void visitEmptyTargetInfo( Clazz clazz, Method method, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo); + public void visitFormalParameterTargetInfo( Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo); + public void visitThrowsTargetInfo( Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo); + public void visitLocalVariableTargetInfo( Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo); + public void visitCatchTargetInfo( Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo); + public void visitOffsetTargetInfo( Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo); + public void visitTypeArgumentTargetInfo( Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo); +} diff --git a/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AllAnnotationVisitor.java index 0aadfe3..b4513d7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.classfile.attribute.annotation.visitor; import proguard.classfile.*; -import proguard.classfile.attribute.Attribute; +import proguard.classfile.attribute.*; import proguard.classfile.attribute.annotation.*; import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.util.SimplifiedVisitor; @@ -102,4 +102,60 @@ implements AttributeVisitor // Visit the annotations. parameterAnnotationsAttribute.annotationsAccept(clazz, method, annotationVisitor); } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + // Visit the annotations. + runtimeVisibleTypeAnnotationsAttribute.annotationsAccept(clazz, annotationVisitor); + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + // Visit the annotations. + runtimeVisibleTypeAnnotationsAttribute.annotationsAccept(clazz, field, annotationVisitor); + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + // Visit the annotations. + runtimeVisibleTypeAnnotationsAttribute.annotationsAccept(clazz, method, annotationVisitor); + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + // Visit the annotations. + runtimeVisibleTypeAnnotationsAttribute.annotationsAccept(clazz, method, codeAttribute, annotationVisitor); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + // Visit the annotations. + runtimeInvisibleTypeAnnotationsAttribute.annotationsAccept(clazz, annotationVisitor); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + // Visit the annotations. + runtimeInvisibleTypeAnnotationsAttribute.annotationsAccept(clazz, field, annotationVisitor); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + // Visit the annotations. + runtimeInvisibleTypeAnnotationsAttribute.annotationsAccept(clazz, method, annotationVisitor); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + // Visit the annotations. + runtimeInvisibleTypeAnnotationsAttribute.annotationsAccept(clazz, method, codeAttribute, annotationVisitor); + } } diff --git a/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java index b728b8b..4413082 100644 --- a/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java +++ b/src/proguard/classfile/attribute/annotation/visitor/AllElementValueVisitor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,11 +21,10 @@ package proguard.classfile.attribute.annotation.visitor; import proguard.classfile.*; -import proguard.classfile.attribute.Attribute; +import proguard.classfile.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 @@ -158,6 +157,12 @@ implements AttributeVisitor, } + public void visitAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, Annotation annotation) + { + annotation.elementValuesAccept(clazz, this); + } + + // Implementations for ElementValueVisitor. public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotatedClassVisitor.java index 305928e..241e9e6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 7833f7e..6bb2454 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 d6ec3ca..ad7b316 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 @@ package proguard.classfile.attribute.annotation.visitor; import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; import proguard.classfile.attribute.annotation.Annotation; -import proguard.classfile.util.SimplifiedVisitor; import proguard.util.*; /** @@ -92,6 +92,15 @@ implements AnnotationVisitor } + public void visitAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, Annotation annotation) + { + if (accepted(annotation.getType(clazz))) + { + annotationVisitor.visitAnnotation(clazz, method, codeAttribute, annotation); + } + } + + // Small utility methods. private boolean accepted(String name) diff --git a/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/AnnotationVisitor.java index 8d207af..3225c97 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.classfile.attribute.annotation.visitor; import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; import proguard.classfile.attribute.annotation.Annotation; /** @@ -33,8 +34,9 @@ import proguard.classfile.attribute.annotation.Annotation; */ public interface AnnotationVisitor { - public void visitAnnotation(Clazz clazz, Annotation annotation); - public void visitAnnotation(Clazz clazz, Field field, Annotation annotation); - public void visitAnnotation(Clazz clazz, Method method, Annotation annotation); - public void visitAnnotation(Clazz clazz, Method method, int parameterIndex, Annotation annotation); + public void visitAnnotation(Clazz clazz, Annotation annotation); + public void visitAnnotation(Clazz clazz, Field field, Annotation annotation); + public void visitAnnotation(Clazz clazz, Method method, Annotation annotation); + public void visitAnnotation(Clazz clazz, Method method, int parameterIndex, Annotation annotation); + public void visitAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, Annotation annotation); } diff --git a/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/ElementValueVisitor.java index 2d3a20d..453c14b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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/TypeAnnotationVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/TypeAnnotationVisitor.java new file mode 100644 index 0000000..3a01887 --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/visitor/TypeAnnotationVisitor.java @@ -0,0 +1,41 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.CodeAttribute; +import proguard.classfile.attribute.annotation.*; + +/** + * This interface specifies the methods for a visitor of + * TypeAnnotation instances. Note that there is only a single + * implementation of TypeAnnotation, such that this interface + * is not strictly necessary as a visitor. + * + * @author Eric Lafortune + */ +public interface TypeAnnotationVisitor +{ + public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation); + public void visitTypeAnnotation(Clazz clazz, Field field, TypeAnnotation typeAnnotation); + public void visitTypeAnnotation(Clazz clazz, Method method, TypeAnnotation typeAnnotation); + public void visitTypeAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation); +} diff --git a/src/proguard/classfile/attribute/annotation/visitor/TypePathInfoVisitor.java b/src/proguard/classfile/attribute/annotation/visitor/TypePathInfoVisitor.java new file mode 100644 index 0000000..ab7d51b --- /dev/null +++ b/src/proguard/classfile/attribute/annotation/visitor/TypePathInfoVisitor.java @@ -0,0 +1,41 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.CodeAttribute; +import proguard.classfile.attribute.annotation.*; + +/** + * This interface specifies the methods for a visitor of + * TypePathInfo instances. Note that there is only a single + * implementation of TypePathInfo, such that this interface + * is not strictly necessary as a visitor. + * + * @author Eric Lafortune + */ +public interface TypePathInfoVisitor +{ + public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo); + public void visitTypePathInfo(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo); + public void visitTypePathInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo); + public void visitTypePathInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo); +} diff --git a/src/proguard/classfile/attribute/preverification/DoubleType.java b/src/proguard/classfile/attribute/preverification/DoubleType.java index 1bc3e5d..1f0478d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 c58cd0a..ee0fe94 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 4f0d72e..09890f2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 9c43cae..9d8144a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 f722d73..681c9ab 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 c986165..dafac5a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 be74df0..be4e08d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 fe0d85f..00b27a7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 4ea370a..6b54277 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 4384aae..63b9058 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 a3bd824..694ed2a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 51e69fb..9b7bbfd 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 01890f3..9b2f43b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 3de059f..a6f9ca6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 02dd1a2..9804c53 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 7b2bfa9..fcbcd7d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 7e4a0fd..1b9de74 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 02c3872..22ad72f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 ada9ce8..71d2c3e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 5e4cf88..f269f6e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 2a3e9e7..cf39ca2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 9d8801c..701451e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 index d70803c..6110325 100644 --- a/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java +++ b/src/proguard/classfile/attribute/visitor/AllBootstrapMethodInfoVisitor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.visitor; -import proguard.classfile.*; +import proguard.classfile.Clazz; import proguard.classfile.attribute.*; import proguard.classfile.util.SimplifiedVisitor; diff --git a/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java b/src/proguard/classfile/attribute/visitor/AllExceptionInfoVisitor.java index 927bfd9..9b6c9de 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 index 2422218..b1005c8 100644 --- a/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java +++ b/src/proguard/classfile/attribute/visitor/AllInnerClassesInfoVisitor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.visitor; -import proguard.classfile.*; +import proguard.classfile.Clazz; import proguard.classfile.attribute.*; import proguard.classfile.util.SimplifiedVisitor; diff --git a/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java b/src/proguard/classfile/attribute/visitor/AttributeNameFilter.java index 0db77d5..14c1edc 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +93,7 @@ implements AttributeVisitor { if (accepted(clazz, unknownAttribute)) { - unknownAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitUnknownAttribute(clazz, unknownAttribute); } } @@ -102,7 +102,7 @@ implements AttributeVisitor { if (accepted(clazz, bootstrapMethodsAttribute)) { - bootstrapMethodsAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute); } } @@ -111,7 +111,7 @@ implements AttributeVisitor { if (accepted(clazz, sourceFileAttribute)) { - sourceFileAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitSourceFileAttribute(clazz, sourceFileAttribute); } } @@ -120,7 +120,7 @@ implements AttributeVisitor { if (accepted(clazz, sourceDirAttribute)) { - sourceDirAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitSourceDirAttribute(clazz, sourceDirAttribute); } } @@ -129,7 +129,7 @@ implements AttributeVisitor { if (accepted(clazz, innerClassesAttribute)) { - innerClassesAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitInnerClassesAttribute(clazz, innerClassesAttribute); } } @@ -138,7 +138,7 @@ implements AttributeVisitor { if (accepted(clazz, enclosingMethodAttribute)) { - enclosingMethodAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitEnclosingMethodAttribute(clazz, enclosingMethodAttribute); } } @@ -147,7 +147,7 @@ implements AttributeVisitor { if (accepted(clazz, deprecatedAttribute)) { - deprecatedAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitDeprecatedAttribute(clazz, deprecatedAttribute); } } @@ -156,7 +156,7 @@ implements AttributeVisitor { if (accepted(clazz, deprecatedAttribute)) { - deprecatedAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitDeprecatedAttribute(clazz, field, deprecatedAttribute); } } @@ -165,7 +165,7 @@ implements AttributeVisitor { if (accepted(clazz, deprecatedAttribute)) { - deprecatedAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitDeprecatedAttribute(clazz, method, deprecatedAttribute); } } @@ -174,7 +174,7 @@ implements AttributeVisitor { if (accepted(clazz, syntheticAttribute)) { - syntheticAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitSyntheticAttribute(clazz, syntheticAttribute); } } @@ -183,7 +183,7 @@ implements AttributeVisitor { if (accepted(clazz, syntheticAttribute)) { - syntheticAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitSyntheticAttribute(clazz, field, syntheticAttribute); } } @@ -192,7 +192,7 @@ implements AttributeVisitor { if (accepted(clazz, syntheticAttribute)) { - syntheticAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitSyntheticAttribute(clazz, method, syntheticAttribute); } } @@ -201,7 +201,7 @@ implements AttributeVisitor { if (accepted(clazz, signatureAttribute)) { - signatureAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitSignatureAttribute(clazz, signatureAttribute); } } @@ -210,7 +210,7 @@ implements AttributeVisitor { if (accepted(clazz, signatureAttribute)) { - signatureAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitSignatureAttribute(clazz, field, signatureAttribute); } } @@ -219,7 +219,7 @@ implements AttributeVisitor { if (accepted(clazz, signatureAttribute)) { - signatureAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitSignatureAttribute(clazz, method, signatureAttribute); } } @@ -228,7 +228,16 @@ implements AttributeVisitor { if (accepted(clazz, constantValueAttribute)) { - constantValueAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitConstantValueAttribute(clazz, field, constantValueAttribute); + } + } + + + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute exceptionsAttribute) + { + if (accepted(clazz, exceptionsAttribute)) + { + attributeVisitor.visitMethodParametersAttribute(clazz, method, exceptionsAttribute); } } @@ -237,7 +246,7 @@ implements AttributeVisitor { if (accepted(clazz, exceptionsAttribute)) { - exceptionsAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitExceptionsAttribute(clazz, method, exceptionsAttribute); } } @@ -246,7 +255,7 @@ implements AttributeVisitor { if (accepted(clazz, codeAttribute)) { - codeAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitCodeAttribute(clazz, method, codeAttribute); } } @@ -255,7 +264,7 @@ implements AttributeVisitor { if (accepted(clazz, stackMapAttribute)) { - stackMapAttribute.accept(clazz, method, codeAttribute, attributeVisitor); + attributeVisitor.visitStackMapAttribute(clazz, method, codeAttribute, stackMapAttribute); } } @@ -264,7 +273,7 @@ implements AttributeVisitor { if (accepted(clazz, stackMapTableAttribute)) { - stackMapTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor); + attributeVisitor.visitStackMapTableAttribute(clazz, method, codeAttribute, stackMapTableAttribute); } } @@ -273,7 +282,7 @@ implements AttributeVisitor { if (accepted(clazz, lineNumberTableAttribute)) { - lineNumberTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor); + attributeVisitor.visitLineNumberTableAttribute(clazz, method, codeAttribute, lineNumberTableAttribute); } } @@ -282,7 +291,7 @@ implements AttributeVisitor { if (accepted(clazz, localVariableTableAttribute)) { - localVariableTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor); + attributeVisitor.visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute); } } @@ -291,7 +300,7 @@ implements AttributeVisitor { if (accepted(clazz, localVariableTypeTableAttribute)) { - localVariableTypeTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor); + attributeVisitor.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute); } } @@ -300,7 +309,7 @@ implements AttributeVisitor { if (accepted(clazz, runtimeVisibleAnnotationsAttribute)) { - runtimeVisibleAnnotationsAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, runtimeVisibleAnnotationsAttribute); } } @@ -309,7 +318,7 @@ implements AttributeVisitor { if (accepted(clazz, runtimeVisibleAnnotationsAttribute)) { - runtimeVisibleAnnotationsAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, field, runtimeVisibleAnnotationsAttribute); } } @@ -318,7 +327,7 @@ implements AttributeVisitor { if (accepted(clazz, runtimeVisibleAnnotationsAttribute)) { - runtimeVisibleAnnotationsAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, method, runtimeVisibleAnnotationsAttribute); } } @@ -327,7 +336,7 @@ implements AttributeVisitor { if (accepted(clazz, runtimeInvisibleAnnotationsAttribute)) { - runtimeInvisibleAnnotationsAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, runtimeInvisibleAnnotationsAttribute); } } @@ -336,7 +345,7 @@ implements AttributeVisitor { if (accepted(clazz, runtimeInvisibleAnnotationsAttribute)) { - runtimeInvisibleAnnotationsAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, field, runtimeInvisibleAnnotationsAttribute); } } @@ -345,7 +354,7 @@ implements AttributeVisitor { if (accepted(clazz, runtimeInvisibleAnnotationsAttribute)) { - runtimeInvisibleAnnotationsAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, method, runtimeInvisibleAnnotationsAttribute); } } @@ -354,7 +363,7 @@ implements AttributeVisitor { if (accepted(clazz, runtimeVisibleParameterAnnotationsAttribute)) { - runtimeVisibleParameterAnnotationsAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitRuntimeVisibleParameterAnnotationsAttribute(clazz, method, runtimeVisibleParameterAnnotationsAttribute); } } @@ -363,7 +372,79 @@ implements AttributeVisitor { if (accepted(clazz, runtimeInvisibleParameterAnnotationsAttribute)) { - runtimeInvisibleParameterAnnotationsAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitRuntimeInvisibleParameterAnnotationsAttribute(clazz, method, runtimeInvisibleParameterAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (accepted(clazz, runtimeVisibleTypeAnnotationsAttribute)) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (accepted(clazz, runtimeVisibleTypeAnnotationsAttribute)) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (accepted(clazz, runtimeVisibleTypeAnnotationsAttribute)) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (accepted(clazz, runtimeVisibleTypeAnnotationsAttribute)) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (accepted(clazz, runtimeInvisibleTypeAnnotationsAttribute)) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (accepted(clazz, runtimeInvisibleTypeAnnotationsAttribute)) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (accepted(clazz, runtimeInvisibleTypeAnnotationsAttribute)) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (accepted(clazz, runtimeInvisibleTypeAnnotationsAttribute)) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeInvisibleTypeAnnotationsAttribute); } } @@ -372,7 +453,7 @@ implements AttributeVisitor { if (accepted(clazz, annotationDefaultAttribute)) { - annotationDefaultAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitAnnotationDefaultAttribute(clazz, method, annotationDefaultAttribute); } } diff --git a/src/proguard/classfile/attribute/visitor/AttributeVisitor.java b/src/proguard/classfile/attribute/visitor/AttributeVisitor.java index 76c1ab9..a9fc6b6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +62,9 @@ public interface AttributeVisitor // Attributes that are attached to methods. - public void visitExceptionsAttribute( Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute); - public void visitCodeAttribute( Clazz clazz, Method method, CodeAttribute codeAttribute); + public void visitMethodParametersAttribute( Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute); + public void visitExceptionsAttribute( Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute); + public void visitCodeAttribute( Clazz clazz, Method method, CodeAttribute codeAttribute); // Attributes that are attached to code attributes. @@ -86,5 +87,15 @@ public interface AttributeVisitor public void visitRuntimeVisibleParameterAnnotationsAttribute( Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute); public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute); + public void visitRuntimeVisibleTypeAnnotationsAttribute( Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute); + public void visitRuntimeVisibleTypeAnnotationsAttribute( Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute); + public void visitRuntimeVisibleTypeAnnotationsAttribute( Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute); + public void visitRuntimeVisibleTypeAnnotationsAttribute( Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute); + + public void visitRuntimeInvisibleTypeAnnotationsAttribute( Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute); + public void visitRuntimeInvisibleTypeAnnotationsAttribute( Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute); + public void visitRuntimeInvisibleTypeAnnotationsAttribute( Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute); + public void visitRuntimeInvisibleTypeAnnotationsAttribute( Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute); + public void visitAnnotationDefaultAttribute( Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute); } diff --git a/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java b/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java index 9aab92e..fb2a9d6 100755 --- a/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java +++ b/src/proguard/classfile/attribute/visitor/BootstrapMethodInfoVisitor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,10 +20,8 @@ */ package proguard.classfile.attribute.visitor; -import proguard.classfile.*; -import proguard.classfile.attribute.*; - -import java.beans.MethodDescriptor; +import proguard.classfile.Clazz; +import proguard.classfile.attribute.BootstrapMethodInfo; /** diff --git a/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java b/src/proguard/classfile/attribute/visitor/ExceptionInfoVisitor.java index 4a765f2..953dc06 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 b373493..f9e1a03 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 189b3d0..5a6400d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 c888d63..dd17bea 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 f992e6d..c37e9d7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 37c0639..968f852 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 +220,15 @@ public class MultiAttributeVisitor implements AttributeVisitor } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + for (int index = 0; index < attributeVisitors.length; index++) + { + attributeVisitors[index].visitMethodParametersAttribute(clazz, method, methodParametersAttribute); + } + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { for (int index = 0; index < attributeVisitors.length; index++) @@ -355,6 +364,78 @@ public class MultiAttributeVisitor implements AttributeVisitor } + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + for (int index = 0; index < attributeVisitors.length; index++) + { + attributeVisitors[index].visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + for (int index = 0; index < attributeVisitors.length; index++) + { + attributeVisitors[index].visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + for (int index = 0; index < attributeVisitors.length; index++) + { + attributeVisitors[index].visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + for (int index = 0; index < attributeVisitors.length; index++) + { + attributeVisitors[index].visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + for (int index = 0; index < attributeVisitors.length; index++) + { + attributeVisitors[index].visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + for (int index = 0; index < attributeVisitors.length; index++) + { + attributeVisitors[index].visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + for (int index = 0; index < attributeVisitors.length; index++) + { + attributeVisitors[index].visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + for (int index = 0; index < attributeVisitors.length; index++) + { + attributeVisitors[index].visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) { 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 index 2ccc09c..4a54f75 100644 --- a/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java +++ b/src/proguard/classfile/attribute/visitor/NonEmptyAttributeFilter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -24,7 +24,6 @@ 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 @@ -54,7 +53,7 @@ implements AttributeVisitor public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) { - unknownAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitUnknownAttribute(clazz, unknownAttribute); } @@ -62,20 +61,20 @@ implements AttributeVisitor { if (bootstrapMethodsAttribute.u2bootstrapMethodsCount > 0) { - bootstrapMethodsAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute); } } public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) { - sourceFileAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitSourceFileAttribute(clazz, sourceFileAttribute); } public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) { - sourceDirAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitSourceDirAttribute(clazz, sourceDirAttribute); } @@ -83,74 +82,83 @@ implements AttributeVisitor { if (innerClassesAttribute.u2classesCount > 0) { - innerClassesAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitInnerClassesAttribute(clazz, innerClassesAttribute); } } public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) { - enclosingMethodAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitEnclosingMethodAttribute(clazz, enclosingMethodAttribute); } public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) { - deprecatedAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitDeprecatedAttribute(clazz, deprecatedAttribute); } public void visitDeprecatedAttribute(Clazz clazz, Field field, DeprecatedAttribute deprecatedAttribute) { - deprecatedAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitDeprecatedAttribute(clazz, field, deprecatedAttribute); } public void visitDeprecatedAttribute(Clazz clazz, Method method, DeprecatedAttribute deprecatedAttribute) { - deprecatedAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitDeprecatedAttribute(clazz, method, deprecatedAttribute); } public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) { - syntheticAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitSyntheticAttribute(clazz, syntheticAttribute); } public void visitSyntheticAttribute(Clazz clazz, Field field, SyntheticAttribute syntheticAttribute) { - syntheticAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitSyntheticAttribute(clazz, field, syntheticAttribute); } public void visitSyntheticAttribute(Clazz clazz, Method method, SyntheticAttribute syntheticAttribute) { - syntheticAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitSyntheticAttribute(clazz, method, syntheticAttribute); } public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) { - signatureAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitSignatureAttribute(clazz, signatureAttribute); } public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute signatureAttribute) { - signatureAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitSignatureAttribute(clazz, field, signatureAttribute); } public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute) { - signatureAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitSignatureAttribute(clazz, method, signatureAttribute); } public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) { - constantValueAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitConstantValueAttribute(clazz, field, constantValueAttribute); + } + + + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute exceptionsAttribute) + { + if (exceptionsAttribute.u1parametersCount > 0) + { + attributeVisitor.visitMethodParametersAttribute(clazz, method, exceptionsAttribute); + } } @@ -158,14 +166,14 @@ implements AttributeVisitor { if (exceptionsAttribute.u2exceptionIndexTableLength > 0) { - exceptionsAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitExceptionsAttribute(clazz, method, exceptionsAttribute); } } public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { - codeAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitCodeAttribute(clazz, method, codeAttribute); } @@ -173,7 +181,7 @@ implements AttributeVisitor { if (stackMapAttribute.u2stackMapFramesCount > 0) { - stackMapAttribute.accept(clazz, method, codeAttribute, attributeVisitor); + attributeVisitor.visitStackMapAttribute(clazz, method, codeAttribute, stackMapAttribute); } } @@ -182,7 +190,7 @@ implements AttributeVisitor { if (stackMapTableAttribute.u2stackMapFramesCount > 0) { - stackMapTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor); + attributeVisitor.visitStackMapTableAttribute(clazz, method, codeAttribute, stackMapTableAttribute); } } @@ -191,7 +199,7 @@ implements AttributeVisitor { if (lineNumberTableAttribute.u2lineNumberTableLength > 0) { - lineNumberTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor); + attributeVisitor.visitLineNumberTableAttribute(clazz, method, codeAttribute, lineNumberTableAttribute); } } @@ -200,7 +208,7 @@ implements AttributeVisitor { if (localVariableTableAttribute.u2localVariableTableLength > 0) { - localVariableTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor); + attributeVisitor.visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute); } } @@ -209,7 +217,7 @@ implements AttributeVisitor { if (localVariableTypeTableAttribute.u2localVariableTypeTableLength > 0) { - localVariableTypeTableAttribute.accept(clazz, method, codeAttribute, attributeVisitor); + attributeVisitor.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute); } } @@ -218,7 +226,7 @@ implements AttributeVisitor { if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0) { - runtimeVisibleAnnotationsAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, runtimeVisibleAnnotationsAttribute); } } @@ -227,7 +235,7 @@ implements AttributeVisitor { if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0) { - runtimeVisibleAnnotationsAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, field, runtimeVisibleAnnotationsAttribute); } } @@ -236,7 +244,7 @@ implements AttributeVisitor { if (runtimeVisibleAnnotationsAttribute.u2annotationsCount > 0) { - runtimeVisibleAnnotationsAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, method, runtimeVisibleAnnotationsAttribute); } } @@ -245,7 +253,7 @@ implements AttributeVisitor { if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0) { - runtimeInvisibleAnnotationsAttribute.accept(clazz, attributeVisitor); + attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, runtimeInvisibleAnnotationsAttribute); } } @@ -254,7 +262,7 @@ implements AttributeVisitor { if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0) { - runtimeInvisibleAnnotationsAttribute.accept(clazz, field, attributeVisitor); + attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, field, runtimeInvisibleAnnotationsAttribute); } } @@ -263,31 +271,103 @@ implements AttributeVisitor { if (runtimeInvisibleAnnotationsAttribute.u2annotationsCount > 0) { - runtimeInvisibleAnnotationsAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, method, runtimeInvisibleAnnotationsAttribute); } } public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute) { - if (runtimeVisibleParameterAnnotationsAttribute.u2parametersCount > 0) + if (runtimeVisibleParameterAnnotationsAttribute.u1parametersCount > 0) { - runtimeVisibleParameterAnnotationsAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitRuntimeVisibleParameterAnnotationsAttribute(clazz, method, runtimeVisibleParameterAnnotationsAttribute); } } public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute) { - if (runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount > 0) + if (runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount > 0) + { + attributeVisitor.visitRuntimeInvisibleParameterAnnotationsAttribute(clazz, method, runtimeInvisibleParameterAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (runtimeVisibleTypeAnnotationsAttribute.u2annotationsCount > 0) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (runtimeVisibleTypeAnnotationsAttribute.u2annotationsCount > 0) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (runtimeVisibleTypeAnnotationsAttribute.u2annotationsCount > 0) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (runtimeVisibleTypeAnnotationsAttribute.u2annotationsCount > 0) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (runtimeInvisibleTypeAnnotationsAttribute.u2annotationsCount > 0) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (runtimeInvisibleTypeAnnotationsAttribute.u2annotationsCount > 0) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (runtimeInvisibleTypeAnnotationsAttribute.u2annotationsCount > 0) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (runtimeInvisibleTypeAnnotationsAttribute.u2annotationsCount > 0) { - runtimeInvisibleParameterAnnotationsAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeInvisibleTypeAnnotationsAttribute); } } public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) { - annotationDefaultAttribute.accept(clazz, method, attributeVisitor); + attributeVisitor.visitAnnotationDefaultAttribute(clazz, method, annotationDefaultAttribute); } } diff --git a/src/proguard/classfile/attribute/visitor/ParameterInfoVisitor.java b/src/proguard/classfile/attribute/visitor/ParameterInfoVisitor.java new file mode 100644 index 0000000..9f91c5b --- /dev/null +++ b/src/proguard/classfile/attribute/visitor/ParameterInfoVisitor.java @@ -0,0 +1,37 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.ParameterInfo; + +/** + * This interface specifies the method for a visitor of + * <code>ParameterInfo</code> objects. Note that there is only a single + * implementation of <code>ParameterInfo</code>, such that this interface + * is not strictly necessary as a visitor. + * + * @author Eric Lafortune + */ +public interface ParameterInfoVisitor +{ + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo); +} diff --git a/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java b/src/proguard/classfile/attribute/visitor/RequiredAttributeFilter.java index 58e4e40..176846d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +77,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - unknownAttribute.accept(clazz, optionalAttributeVisitor); + optionalAttributeVisitor.visitUnknownAttribute(clazz, unknownAttribute); } } @@ -86,7 +86,7 @@ implements AttributeVisitor { if (requiredAttributeVisitor != null) { - bootstrapMethodsAttribute.accept(clazz, requiredAttributeVisitor); + requiredAttributeVisitor.visitBootstrapMethodsAttribute(clazz, bootstrapMethodsAttribute); } } @@ -95,7 +95,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - sourceFileAttribute.accept(clazz, optionalAttributeVisitor); + optionalAttributeVisitor.visitSourceFileAttribute(clazz, sourceFileAttribute); } } @@ -104,7 +104,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - sourceDirAttribute.accept(clazz, optionalAttributeVisitor); + optionalAttributeVisitor.visitSourceDirAttribute(clazz, sourceDirAttribute); } } @@ -113,7 +113,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - innerClassesAttribute.accept(clazz, optionalAttributeVisitor); + optionalAttributeVisitor.visitInnerClassesAttribute(clazz, innerClassesAttribute); } } @@ -122,7 +122,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - enclosingMethodAttribute.accept(clazz, optionalAttributeVisitor); + optionalAttributeVisitor.visitEnclosingMethodAttribute(clazz, enclosingMethodAttribute); } } @@ -131,7 +131,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - deprecatedAttribute.accept(clazz, optionalAttributeVisitor); + optionalAttributeVisitor.visitDeprecatedAttribute(clazz, deprecatedAttribute); } } @@ -140,7 +140,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - deprecatedAttribute.accept(clazz, field, optionalAttributeVisitor); + optionalAttributeVisitor.visitDeprecatedAttribute(clazz, field, deprecatedAttribute); } } @@ -149,7 +149,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - deprecatedAttribute.accept(clazz, method, optionalAttributeVisitor); + optionalAttributeVisitor.visitDeprecatedAttribute(clazz, method, deprecatedAttribute); } } @@ -158,7 +158,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - syntheticAttribute.accept(clazz, optionalAttributeVisitor); + optionalAttributeVisitor.visitSyntheticAttribute(clazz, syntheticAttribute); } } @@ -167,7 +167,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - syntheticAttribute.accept(clazz, field, optionalAttributeVisitor); + optionalAttributeVisitor.visitSyntheticAttribute(clazz, field, syntheticAttribute); } } @@ -176,7 +176,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - syntheticAttribute.accept(clazz, method, optionalAttributeVisitor); + optionalAttributeVisitor.visitSyntheticAttribute(clazz, method, syntheticAttribute); } } @@ -185,7 +185,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - signatureAttribute.accept(clazz, optionalAttributeVisitor); + optionalAttributeVisitor.visitSignatureAttribute(clazz, signatureAttribute); } } @@ -194,7 +194,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - signatureAttribute.accept(clazz, field, optionalAttributeVisitor); + optionalAttributeVisitor.visitSignatureAttribute(clazz, field, signatureAttribute); } } @@ -203,7 +203,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - signatureAttribute.accept(clazz, method, optionalAttributeVisitor); + optionalAttributeVisitor.visitSignatureAttribute(clazz, method, signatureAttribute); } } @@ -212,7 +212,16 @@ implements AttributeVisitor { if (requiredAttributeVisitor != null) { - constantValueAttribute.accept(clazz, field, requiredAttributeVisitor); + requiredAttributeVisitor.visitConstantValueAttribute(clazz, field, constantValueAttribute); + } + } + + + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute exceptionsAttribute) + { + if (optionalAttributeVisitor != null) + { + optionalAttributeVisitor.visitMethodParametersAttribute(clazz, method, exceptionsAttribute); } } @@ -221,7 +230,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - exceptionsAttribute.accept(clazz, method, optionalAttributeVisitor); + optionalAttributeVisitor.visitExceptionsAttribute(clazz, method, exceptionsAttribute); } } @@ -230,7 +239,7 @@ implements AttributeVisitor { if (requiredAttributeVisitor != null) { - codeAttribute.accept(clazz, method, requiredAttributeVisitor); + requiredAttributeVisitor.visitCodeAttribute(clazz, method, codeAttribute); } } @@ -239,7 +248,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - stackMapAttribute.accept(clazz, method, codeAttribute, optionalAttributeVisitor); + optionalAttributeVisitor.visitStackMapAttribute(clazz, method, codeAttribute, stackMapAttribute); } } @@ -248,7 +257,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - stackMapTableAttribute.accept(clazz, method, codeAttribute, optionalAttributeVisitor); + optionalAttributeVisitor.visitStackMapTableAttribute(clazz, method, codeAttribute, stackMapTableAttribute); } } @@ -257,7 +266,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - lineNumberTableAttribute.accept(clazz, method, codeAttribute, optionalAttributeVisitor); + optionalAttributeVisitor.visitLineNumberTableAttribute(clazz, method, codeAttribute, lineNumberTableAttribute); } } @@ -266,7 +275,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - localVariableTableAttribute.accept(clazz, method, codeAttribute, optionalAttributeVisitor); + optionalAttributeVisitor.visitLocalVariableTableAttribute(clazz, method, codeAttribute, localVariableTableAttribute); } } @@ -275,7 +284,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - localVariableTypeTableAttribute.accept(clazz, method, codeAttribute, optionalAttributeVisitor); + optionalAttributeVisitor.visitLocalVariableTypeTableAttribute(clazz, method, codeAttribute, localVariableTypeTableAttribute); } } @@ -284,7 +293,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - runtimeVisibleAnnotationsAttribute.accept(clazz, optionalAttributeVisitor); + optionalAttributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, runtimeVisibleAnnotationsAttribute); } } @@ -293,7 +302,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - runtimeVisibleAnnotationsAttribute.accept(clazz, field, optionalAttributeVisitor); + optionalAttributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, field, runtimeVisibleAnnotationsAttribute); } } @@ -302,7 +311,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - runtimeVisibleAnnotationsAttribute.accept(clazz, method, optionalAttributeVisitor); + optionalAttributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz, method, runtimeVisibleAnnotationsAttribute); } } @@ -311,7 +320,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - runtimeInvisibleAnnotationsAttribute.accept(clazz, optionalAttributeVisitor); + optionalAttributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, runtimeInvisibleAnnotationsAttribute); } } @@ -320,7 +329,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - runtimeInvisibleAnnotationsAttribute.accept(clazz, field, optionalAttributeVisitor); + optionalAttributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, field, runtimeInvisibleAnnotationsAttribute); } } @@ -329,7 +338,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - runtimeInvisibleAnnotationsAttribute.accept(clazz, method, optionalAttributeVisitor); + optionalAttributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(clazz, method, runtimeInvisibleAnnotationsAttribute); } } @@ -338,7 +347,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - runtimeVisibleParameterAnnotationsAttribute.accept(clazz, method, optionalAttributeVisitor); + optionalAttributeVisitor.visitRuntimeVisibleParameterAnnotationsAttribute(clazz, method, runtimeVisibleParameterAnnotationsAttribute); } } @@ -347,7 +356,79 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - runtimeInvisibleParameterAnnotationsAttribute.accept(clazz, method, optionalAttributeVisitor); + optionalAttributeVisitor.visitRuntimeInvisibleParameterAnnotationsAttribute(clazz, method, runtimeInvisibleParameterAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (optionalAttributeVisitor != null) + { + optionalAttributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (optionalAttributeVisitor != null) + { + optionalAttributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (optionalAttributeVisitor != null) + { + optionalAttributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + if (optionalAttributeVisitor != null) + { + optionalAttributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeVisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (optionalAttributeVisitor != null) + { + optionalAttributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (optionalAttributeVisitor != null) + { + optionalAttributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (optionalAttributeVisitor != null) + { + optionalAttributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute); + } + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + if (optionalAttributeVisitor != null) + { + optionalAttributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeInvisibleTypeAnnotationsAttribute); } } @@ -356,7 +437,7 @@ implements AttributeVisitor { if (optionalAttributeVisitor != null) { - annotationDefaultAttribute.accept(clazz, method, optionalAttributeVisitor); + optionalAttributeVisitor.visitAnnotationDefaultAttribute(clazz, method, annotationDefaultAttribute); } } } diff --git a/src/proguard/classfile/attribute/visitor/StackSizeComputer.java b/src/proguard/classfile/attribute/visitor/StackSizeComputer.java index b5e02e2..d5cd99d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,11 +21,11 @@ package proguard.classfile.attribute.visitor; import proguard.classfile.*; -import proguard.classfile.visitor.ClassPrinter; import proguard.classfile.attribute.*; import proguard.classfile.instruction.*; import proguard.classfile.instruction.visitor.InstructionVisitor; import proguard.classfile.util.SimplifiedVisitor; +import proguard.classfile.visitor.ClassPrinter; import java.util.Arrays; diff --git a/src/proguard/classfile/constant/ClassConstant.java b/src/proguard/classfile/constant/ClassConstant.java index bbd9b31..fedfefe 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 b4168ce..72d495a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 a4c64cf..9a6f292 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 d552d47..5755b75 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 1709fcb..7d89b39 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 5f0d7f9..9b244ee 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 52f1852..6d4901d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 index 57474aa..1ad3954 100755 --- a/src/proguard/classfile/constant/InvokeDynamicConstant.java +++ b/src/proguard/classfile/constant/InvokeDynamicConstant.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.constant; import proguard.classfile.*; import proguard.classfile.constant.visitor.*; -import proguard.classfile.visitor.*; +import proguard.classfile.visitor.ClassVisitor; /** * This Constant represents an invoke dynamic constant in the constant pool. diff --git a/src/proguard/classfile/constant/LongConstant.java b/src/proguard/classfile/constant/LongConstant.java index 2416f01..2fd1daf 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 index 6cffd9a..09efddd 100755 --- a/src/proguard/classfile/constant/MethodHandleConstant.java +++ b/src/proguard/classfile/constant/MethodHandleConstant.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 @@ public class MethodHandleConstant extends Constant * 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>.. + * ClassReferenceInitializer}</code>. */ public Clazz javaLangInvokeMethodHandleClass; @@ -94,6 +94,14 @@ public class MethodHandleConstant extends Constant /** + * Returns the class name. + */ + public String getClassName(Clazz clazz) + { + return clazz.getRefClassName(u2referenceIndex); + } + + /** * Returns the method/field name. */ public String getName(Clazz clazz) diff --git a/src/proguard/classfile/constant/MethodTypeConstant.java b/src/proguard/classfile/constant/MethodTypeConstant.java index 96c136f..5efd0fe 100644 --- a/src/proguard/classfile/constant/MethodTypeConstant.java +++ b/src/proguard/classfile/constant/MethodTypeConstant.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -22,6 +22,7 @@ package proguard.classfile.constant; import proguard.classfile.*; import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.visitor.ClassVisitor; /** * This Constant represents a method handle constant in the constant pool. @@ -43,6 +44,15 @@ public class MethodTypeConstant extends Constant /** + * 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 MethodTypeConstant. */ public MethodTypeConstant() @@ -79,6 +89,25 @@ public class MethodTypeConstant extends Constant } + /** + * 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); + } + } + } + } + + // Implementations for Constant. public int getTag() diff --git a/src/proguard/classfile/constant/MethodrefConstant.java b/src/proguard/classfile/constant/MethodrefConstant.java index 1ffa236..cb43efc 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 2a4dd66..c82e57e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 0a8fb78..50ac976 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 9b83745..c3475a5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 3707ba9..4eaf304 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 3c36609..940ad45 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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/BootstrapMethodArgumentVisitor.java b/src/proguard/classfile/constant/visitor/BootstrapMethodArgumentVisitor.java new file mode 100644 index 0000000..a5bfb2e --- /dev/null +++ b/src/proguard/classfile/constant/visitor/BootstrapMethodArgumentVisitor.java @@ -0,0 +1,56 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.classfile.constant.visitor; + +import proguard.classfile.Clazz; +import proguard.classfile.attribute.BootstrapMethodInfo; +import proguard.classfile.attribute.visitor.BootstrapMethodInfoVisitor; + +/** + * This BootstrapMethodInfoVisitor lets a given ConstantVisitor visit all + * constant pool entries of the bootstrap methods it visits. + * + * + * @author Eric Lafortune + */ +public class BootstrapMethodArgumentVisitor +implements BootstrapMethodInfoVisitor +{ + private ConstantVisitor constantVisitor; + + /** + * Creates a new BootstrapMethodArgumentVisitor that will delegate to the + * given constant visitor. + */ + public BootstrapMethodArgumentVisitor(ConstantVisitor constantVisitor) + { + this.constantVisitor = constantVisitor; + } + + + // Implementations for BootstrapMethodInfoVisitor. + + public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo) + { + // Check bootstrap method. + bootstrapMethodInfo.methodArgumentsAccept(clazz, constantVisitor); + } +} diff --git a/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java b/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java index 6dce6c5..cfd6c1a 100644 --- a/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java +++ b/src/proguard/classfile/constant/visitor/BootstrapMethodHandleTraveler.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,15 +20,11 @@ */ package proguard.classfile.constant.visitor; -import proguard.classfile.*; +import proguard.classfile.Clazz; 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 diff --git a/src/proguard/classfile/constant/visitor/ConstantTagFilter.java b/src/proguard/classfile/constant/visitor/ConstantTagFilter.java index a3fcc8a..ffff4b3 100644 --- a/src/proguard/classfile/constant/visitor/ConstantTagFilter.java +++ b/src/proguard/classfile/constant/visitor/ConstantTagFilter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.classfile.constant.visitor; import proguard.classfile.Clazz; -import proguard.classfile.constant.*; +import proguard.classfile.constant.Constant; import proguard.classfile.util.SimplifiedVisitor; /** diff --git a/src/proguard/classfile/constant/visitor/ConstantVisitor.java b/src/proguard/classfile/constant/visitor/ConstantVisitor.java index 362d54d..11528b8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java b/src/proguard/classfile/constant/visitor/ExceptClassConstantFilter.java index bff4d1e..82f180d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,13 +20,8 @@ */ package proguard.classfile.constant.visitor; -import proguard.classfile.*; -import proguard.classfile.editor.*; -import proguard.classfile.attribute.*; -import proguard.classfile.attribute.annotation.*; -import proguard.classfile.attribute.preverification.*; +import proguard.classfile.Clazz; import proguard.classfile.constant.ClassConstant; -import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.SimplifiedVisitor; /** diff --git a/src/proguard/classfile/constant/visitor/MethodrefTraveler.java b/src/proguard/classfile/constant/visitor/MethodrefTraveler.java index acd1bc8..f5fffbc 100644 --- a/src/proguard/classfile/constant/visitor/MethodrefTraveler.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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ package proguard.classfile.constant.visitor; import proguard.classfile.Clazz; -import proguard.classfile.attribute.*; import proguard.classfile.constant.*; import proguard.classfile.util.SimplifiedVisitor; diff --git a/src/proguard/classfile/editor/AccessFixer.java b/src/proguard/classfile/editor/AccessFixer.java index d770531..3c41159 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,160 +21,196 @@ 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.*; import proguard.classfile.visitor.*; /** - * This ConstantVisitor fixes the access modifiers of all classes and class - * members that are referenced by the constants that it visits. + * This ClassVisitor fixes the access modifiers of all classes and class + * members that are referenced by the classes that it visits. * * @author Eric Lafortune */ public class AccessFixer -extends SimplifiedVisitor -implements ConstantVisitor, - ClassVisitor, - MemberVisitor +extends ReferencedClassVisitor +implements ClassVisitor { - private MyReferencedClassFinder referencedClassFinder = new MyReferencedClassFinder(); + /** + * Creates a new AccessFixer. + */ + public AccessFixer() + { + // Unfortunately, the inner class must be static to be passed to the + // super constructor. We therefore can't let it refer to this class; + // we'll let this class refer to the inner class instead. + super(new MyAccessFixer()); + } - private Clazz referencingClass; - private Clazz referencedClass; + // Overridden methods for ClassVisitor. - // Implementations for ConstantVisitor. + public void visitProgramClass(ProgramClass programClass) + { + // Remember the referencing class. + ((MyAccessFixer)classVisitor).referencingClass = programClass; - public void visitAnyConstant(Clazz clazz, Constant constant) {} + // Start visiting and fixing the referenced classes and class members. + super.visitProgramClass(programClass); + } - public void visitStringConstant(Clazz clazz, StringConstant stringConstant) + public void visitLibraryClass(LibraryClass libraryClass) { - referencingClass = clazz; - referencedClass = stringConstant.referencedClass; + // Remember the referencing class. + ((MyAccessFixer)classVisitor).referencingClass = libraryClass; - // Make sure the access flags of the referenced class or class member, - // if any, are acceptable. - stringConstant.referencedClassAccept(this); - stringConstant.referencedMemberAccept(this); + // Start visiting and fixing the referenced classes and class members. + super.visitLibraryClass(libraryClass); } - public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + // Overridden methods for MemberVisitor. + + public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { - // Check the bootstrap method. - invokeDynamicConstant.bootstrapMethodHandleAccept(clazz, this); + // Fix the referenced classes and class members. + super.visitProgramMember(programClass, programMethod); + + // Fix overridden or implemented methods higher up the hierarchy. + // We can ignore private and static methods and initializers. + if ((programMethod.getAccessFlags() & (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC)) == 0 && + !ClassUtil.isInitializer(programMethod.getName(programClass))) + { + programClass.hierarchyAccept(false, true, false, false, + new NamedMethodVisitor(programMethod.getName(programClass), + programMethod.getDescriptor(programClass), + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC, + (MemberVisitor)classVisitor))); + } } - public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) + public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) { - // Check the method reference. - clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this); + // Fix the referenced classes and class members. + super.visitLibraryMember(libraryClass, libraryMethod); + + // Fix overridden or implemented methods higher up the hierarchy. + // We can ignore private and static methods and initializers. + if ((libraryMethod.getAccessFlags() & (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC)) == 0 && + !ClassUtil.isInitializer(libraryMethod.getName(libraryClass))) + { + libraryClass.hierarchyAccept(false, true, false, false, + new NamedMethodVisitor(libraryMethod.getName(libraryClass), + libraryMethod.getDescriptor(libraryClass), + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC, + (MemberVisitor)classVisitor))); + } } - public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) - { - referencingClass = clazz; + // Overridden methods for ConstantVisitor. - // Remember the specified class, since it might be different from - // the referenced class that actually contains the class member. - clazz.constantPoolEntryAccept(refConstant.u2classIndex, referencedClassFinder); + public void visitStringConstant(Clazz clazz, StringConstant stringConstant) + { + // Fix the access flags of the referenced class, if any. + super.visitStringConstant(clazz, stringConstant); - // Make sure the access flags of the referenced class member are - // acceptable. - refConstant.referencedMemberAccept(this); + // Fix the access flags of the referenced class member, if any. + stringConstant.referencedMemberAccept((MemberVisitor)classVisitor); } - public void visitClassConstant(Clazz clazz, ClassConstant classConstant) + public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) { - referencingClass = clazz; + // Fix the access flags of the referenced class. + super.visitAnyRefConstant(clazz, refConstant); - // Make sure the access flags of the referenced class are acceptable. - classConstant.referencedClassAccept(this); + // Fix the access flags of the referenced class member. + refConstant.referencedMemberAccept((MemberVisitor)classVisitor); } - // Implementations for ClassVisitor. + /** + * This ClassVisitor and MemberVisitor fixes the access flags of the + * classes and class members that it visits, relative to the referencing + * class. + */ + private static class MyAccessFixer + extends SimplifiedVisitor + implements ClassVisitor, + MemberVisitor + { + private Clazz referencingClass; - public void visitLibraryClass(LibraryClass libraryClass) {} + // Implementations for ClassVisitor. - public void visitProgramClass(ProgramClass programClass) - { - int currentAccessFlags = programClass.getAccessFlags(); - int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags); + public void visitLibraryClass(LibraryClass libraryClass) {} - // Compute the required access level. - Clazz referencingClass = this.referencingClass; - int requiredAccessLevel = - inSamePackage(programClass, referencingClass) ? AccessUtil.PACKAGE_VISIBLE : - AccessUtil.PUBLIC; - // Fix the class access flags if necessary. - if (currentAccessLevel < requiredAccessLevel) + public void visitProgramClass(ProgramClass programClass) { - programClass.u2accessFlags = - AccessUtil.replaceAccessFlags(currentAccessFlags, - AccessUtil.accessFlags(requiredAccessLevel)); + int currentAccessFlags = programClass.getAccessFlags(); + int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags); + + // Compute the required access level. + int requiredAccessLevel = + inSamePackage(programClass, referencingClass) ? + AccessUtil.PACKAGE_VISIBLE : + AccessUtil.PUBLIC; + + // Fix the class access flags if necessary. + if (currentAccessLevel < requiredAccessLevel) + { + programClass.u2accessFlags = + AccessUtil.replaceAccessFlags(currentAccessFlags, + AccessUtil.accessFlags(requiredAccessLevel)); + } } - } - // Implementations for MemberVisitor. + // Implementations for MemberVisitor. - public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) {} + public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) {} - public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) - { - int currentAccessFlags = programMember.getAccessFlags(); - int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags); - - // Compute the required access level. - int requiredAccessLevel = - programClass.equals(referencingClass) ? AccessUtil.PRIVATE : - inSamePackage(programClass, referencingClass) ? AccessUtil.PACKAGE_VISIBLE : - referencedClass.extends_(referencingClass) && - referencingClass.extends_(programClass) ? AccessUtil.PROTECTED : - AccessUtil.PUBLIC; - - // Fix the class member access flags if necessary. - if (currentAccessLevel < requiredAccessLevel) + public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) { - programMember.u2accessFlags = - AccessUtil.replaceAccessFlags(currentAccessFlags, - AccessUtil.accessFlags(requiredAccessLevel)); + int currentAccessFlags = programMember.getAccessFlags(); + int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags); + + // Compute the required access level. + int requiredAccessLevel = + programClass.equals(referencingClass) ? AccessUtil.PRIVATE : + inSamePackage(programClass, referencingClass) ? AccessUtil.PACKAGE_VISIBLE : + programClass.extends_(referencingClass) && + referencingClass.extends_(programClass) ? AccessUtil.PROTECTED : + AccessUtil.PUBLIC; + + // Fix the class member access flags if necessary. + if (currentAccessLevel < requiredAccessLevel) + { + programMember.u2accessFlags = + AccessUtil.replaceAccessFlags(currentAccessFlags, + AccessUtil.accessFlags(requiredAccessLevel)); + } } - } - /** - * This ConstantVisitor returns the referenced class of the class constant - * that it visits. - */ - private class MyReferencedClassFinder - extends SimplifiedVisitor - implements ConstantVisitor - { - // Implementations for ConstantVisitor. - public void visitClassConstant(Clazz clazz, ClassConstant classConstant) + // Small utility methods. + + /** + * Returns whether the two given classes are in the same package. + */ + private boolean inSamePackage(ProgramClass class1, Clazz class2) { - referencedClass = classConstant.referencedClass; + return ClassUtil.internalPackageName(class1.getName()).equals( + ClassUtil.internalPackageName(class2.getName())); } } - - - // Small utility methods. - - private boolean inSamePackage(ProgramClass class1, Clazz class2) - { - return ClassUtil.internalPackageName(class1.getName()).equals( - ClassUtil.internalPackageName(class2.getName())); - } } diff --git a/src/proguard/classfile/editor/AnnotationAdder.java b/src/proguard/classfile/editor/AnnotationAdder.java index 0389ab1..3a3fad0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 a175c33..53cee40 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 ad4ecc0..9abea45 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 @@ import proguard.classfile.attribute.preverification.*; import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.util.SimplifiedVisitor; +import java.lang.reflect.Array; +import java.util.Arrays; + /** * This AttributeVisitor adds all attributes that it visits to the given * target class, class member, or attribute. @@ -41,6 +44,7 @@ implements AttributeVisitor private static final int[] EMPTY_INTS = new int[0]; private static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0]; private static final ExceptionInfo[] EMPTY_EXCEPTIONS = new ExceptionInfo[0]; + private static final Annotation[] EMPTY_ANNOTATIONS = new Annotation[0]; private final ProgramClass targetClass; @@ -214,6 +218,24 @@ implements AttributeVisitor } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + // Create a new local variable table attribute. + MethodParametersAttribute newMethodParametersAttribute = + new MethodParametersAttribute(constantAdder.addConstant(clazz, methodParametersAttribute.u2attributeNameIndex), + methodParametersAttribute.u1parametersCount, + new ParameterInfo[methodParametersAttribute.u1parametersCount]); + + // Add the local variables. + methodParametersAttribute.parametersAccept(clazz, + method, + new ParameterInfoAdder(targetClass, newMethodParametersAttribute)); + + // Add it to the target. + attributesEditor.addAttribute(newMethodParametersAttribute); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { // Create a new exceptions attribute. @@ -399,11 +421,16 @@ implements AttributeVisitor public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute) { // Create a new annotations attribute. + Annotation[][] parameterAnnotations = + new Annotation[runtimeVisibleParameterAnnotationsAttribute.u1parametersCount][]; + + Arrays.fill(parameterAnnotations, EMPTY_ANNOTATIONS); + RuntimeVisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute = new RuntimeVisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleParameterAnnotationsAttribute.u2attributeNameIndex), 0, - new int[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount], - new Annotation[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount][]); + new int[runtimeVisibleParameterAnnotationsAttribute.u1parametersCount], + parameterAnnotations); // Add the annotations. runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz, @@ -419,11 +446,16 @@ implements AttributeVisitor public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute) { // Create a new annotations attribute. + Annotation[][] parameterAnnotations = + new Annotation[runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount][]; + + Arrays.fill(parameterAnnotations, EMPTY_ANNOTATIONS); + RuntimeInvisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute = new RuntimeInvisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleParameterAnnotationsAttribute.u2attributeNameIndex), 0, - new int[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount], - new Annotation[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount][]); + new int[runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount], + parameterAnnotations); // Add the annotations. runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz, diff --git a/src/proguard/classfile/editor/AttributeSorter.java b/src/proguard/classfile/editor/AttributeSorter.java index 23fe027..8f1f414 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 f50b8f1..ce38a6b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,27 @@ public class AttributesEditor /** + * Finds the specified attribute in the target. + */ + public Attribute findAttribute(String attributeName) + { + // What's the target? + return + targetAttribute != null ? + findAttribute(targetAttribute.u2attributesCount, + targetAttribute.attributes, + attributeName) : + targetMember != null ? + findAttribute(targetMember.u2attributesCount, + targetMember.attributes, + attributeName) : + findAttribute(targetClass.u2attributesCount, + targetClass.attributes, + attributeName); + } + + + /** * Adds the given attribute to the target. */ public void addAttribute(Attribute attribute) @@ -171,17 +192,17 @@ public class AttributesEditor // Small utility methods. /** - * Tries put the given attribute in place of an existing attribute of the - * same name, returning whether it was present. + * Tries to put the given attribute in place of an existing attribute of + * the same name, returning whether it was present. */ private boolean replaceAttribute(int attributesCount, Attribute[] attributes, Attribute attribute) { // Find the attribute with the same name. - int index = findAttribute(attributesCount, - attributes, - attribute.getAttributeName(targetClass)); + int index = findAttributeIndex(attributesCount, + attributes, + attribute.getAttributeName(targetClass)); if (index < 0) { return false; @@ -228,9 +249,9 @@ public class AttributesEditor String attributeName) { // Find the attribute. - int index = findAttribute(attributesCount, - attributes, - attributeName); + int index = findAttributeIndex(attributesCount, + attributes, + attributeName); if (index < 0) { return attributesCount; @@ -252,13 +273,15 @@ public class AttributesEditor * Finds the index of the attribute with the given name in the given * array of attributes. */ - private int findAttribute(int attributesCount, - Attribute[] attributes, - String attributeName) + private int findAttributeIndex(int attributesCount, + Attribute[] attributes, + String attributeName) { for (int index = 0; index < attributesCount; index++) { - if (attributes[index].getAttributeName(targetClass).equals(attributeName)) + Attribute attribute = attributes[index]; + + if (attribute.getAttributeName(targetClass).equals(attributeName)) { return index; } @@ -266,4 +289,26 @@ public class AttributesEditor return -1; } + + + /** + * Finds the attribute with the given name in the given + * array of attributes. + */ + private Attribute findAttribute(int attributesCount, + Attribute[] attributes, + String attributeName) + { + for (int index = 0; index < attributesCount; index++) + { + Attribute attribute = attributes[index]; + + if (attribute.getAttributeName(targetClass).equals(attributeName)) + { + return attribute; + } + } + + return null; + } } diff --git a/src/proguard/classfile/editor/BootstrapMethodInfoAdder.java b/src/proguard/classfile/editor/BootstrapMethodInfoAdder.java new file mode 100644 index 0000000..260a561 --- /dev/null +++ b/src/proguard/classfile/editor/BootstrapMethodInfoAdder.java @@ -0,0 +1,86 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.BootstrapMethodInfoVisitor; + +/** + * This BootstrapMethodInfoVisitor adds all bootstrap methods that it visits to + * the given target bootstrap methods attribute. + */ +public class BootstrapMethodInfoAdder +implements BootstrapMethodInfoVisitor +{ + private final ConstantAdder constantAdder; + private final BootstrapMethodsAttributeEditor bootstrapMethodsAttributeEditor; + + private int bootstrapMethodIndex; + + + /** + * Creates a new BootstrapMethodInfoAdder that will copy bootstrap methods + * into the given bootstrap methods attribute. + */ + public BootstrapMethodInfoAdder(ProgramClass targetClass, + BootstrapMethodsAttribute targetBootstrapMethodsAttribute) + { + this.constantAdder = new ConstantAdder(targetClass); + this.bootstrapMethodsAttributeEditor = new BootstrapMethodsAttributeEditor(targetBootstrapMethodsAttribute); + } + + + /** + * Returns the index of the most recently added bootstrap method. + */ + public int getBootstrapMethodIndex() + { + return bootstrapMethodIndex; + } + + + // Implementations for BootstrapMethodInfoVisitor. + + public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo) + { + // Copy the method arguments. + int methodArgumentCount = bootstrapMethodInfo.u2methodArgumentCount; + int[] methodArguments = bootstrapMethodInfo.u2methodArguments; + int[] newMethodArguments = new int[methodArgumentCount]; + + for (int index = 0; index < methodArgumentCount; index++) + { + newMethodArguments[index] = + constantAdder.addConstant(clazz, methodArguments[index]); + } + + // Create a new bootstrap method. + BootstrapMethodInfo newBootstrapMethodInfo = + new BootstrapMethodInfo(constantAdder.addConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex), + methodArgumentCount, + newMethodArguments); + + // Add it to the target. + bootstrapMethodIndex = + bootstrapMethodsAttributeEditor.addBootstrapMethodInfo(newBootstrapMethodInfo); + } +}
\ No newline at end of file diff --git a/src/proguard/classfile/editor/BootstrapMethodRemapper.java b/src/proguard/classfile/editor/BootstrapMethodRemapper.java new file mode 100644 index 0000000..76d2766 --- /dev/null +++ b/src/proguard/classfile/editor/BootstrapMethodRemapper.java @@ -0,0 +1,88 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.*; + +/** + * This ConstantVisitor remaps all possible indices of bootstrap methods + * of the constants that it visits, based on a given index map. + * + * @author Eric Lafortune + */ +public class BootstrapMethodRemapper +extends SimplifiedVisitor +implements ConstantVisitor +{ + private int[] constantIndexMap; + + + /** + * Sets the given mapping of old constant pool entry indexes to their new + * indexes. + */ + public void setConstantIndexMap(int[] constantIndexMap) + { + this.constantIndexMap = constantIndexMap; + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + { + invokeDynamicConstant.u2bootstrapMethodAttributeIndex = + remapConstantIndex(invokeDynamicConstant.u2bootstrapMethodAttributeIndex); + } + + + // Small utility methods. + + /** + * Returns the new bootstrap method index of the entry at the + * given index. + */ + private int remapConstantIndex(int constantIndex) + { + int remappedConstantIndex = constantIndexMap[constantIndex]; + if (remappedConstantIndex < 0) + { + throw new IllegalArgumentException("Can't remap constant index ["+constantIndex+"]"); + } + + return remappedConstantIndex; + } +} diff --git a/src/proguard/classfile/editor/BootstrapMethodsAttributeAdder.java b/src/proguard/classfile/editor/BootstrapMethodsAttributeAdder.java new file mode 100644 index 0000000..1488b9b --- /dev/null +++ b/src/proguard/classfile/editor/BootstrapMethodsAttributeAdder.java @@ -0,0 +1,91 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.BootstrapMethodInfoVisitor; + +/** + * This BootstrapMethodInfoVisitor adds all bootstrap methods that it visits to + * the given target class, creating a bootstrap methods attribute if necessary. + */ +public class BootstrapMethodsAttributeAdder +implements BootstrapMethodInfoVisitor +{ + private final ProgramClass targetClass; + private final ConstantPoolEditor constantPoolEditor; + private BootstrapMethodInfoAdder bootstrapMethodInfoAdder; + + + /** + * Creates a new BootstrapMethodsAttributeAdder that will copy bootstrap + * methods into the given target class/ + */ + public BootstrapMethodsAttributeAdder(ProgramClass targetClass) + { + this.targetClass = targetClass; + this.constantPoolEditor = new ConstantPoolEditor(targetClass); + } + + + /** + * Returns the index of the most recently added bootstrap method. + */ + public int getBootstrapMethodIndex() + { + return bootstrapMethodInfoAdder.getBootstrapMethodIndex(); + } + + + // Implementations for BootstrapMethodInfoVisitor. + + public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo) + { + // Make sure we have a bootstrap methods attribute adder. + if (bootstrapMethodInfoAdder == null) + { + // Make sure we have a target bootstrap methods attribute. + AttributesEditor attributesEditor = + new AttributesEditor(targetClass, false); + + BootstrapMethodsAttribute targetBootstrapMethodsAttribute = + (BootstrapMethodsAttribute)attributesEditor.findAttribute(ClassConstants.ATTR_BootstrapMethods); + + if (targetBootstrapMethodsAttribute == null) + { + targetBootstrapMethodsAttribute = + new BootstrapMethodsAttribute(constantPoolEditor.addUtf8Constant(ClassConstants.ATTR_BootstrapMethods), + 0, + new BootstrapMethodInfo[0]); + + attributesEditor.addAttribute(targetBootstrapMethodsAttribute); + } + + // Create a bootstrap method adder for it. + bootstrapMethodInfoAdder = new BootstrapMethodInfoAdder(targetClass, + targetBootstrapMethodsAttribute); + } + + // Delegate to the bootstrap method adder. + bootstrapMethodInfoAdder.visitBootstrapMethodInfo(clazz, bootstrapMethodInfo); + } +}
\ No newline at end of file diff --git a/src/proguard/classfile/editor/BootstrapMethodsAttributeEditor.java b/src/proguard/classfile/editor/BootstrapMethodsAttributeEditor.java new file mode 100644 index 0000000..d00d47a --- /dev/null +++ b/src/proguard/classfile/editor/BootstrapMethodsAttributeEditor.java @@ -0,0 +1,60 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.classfile.editor; + +import proguard.classfile.attribute.*; +import proguard.util.ArrayUtil; + +/** + * This class can add bootstrap methods to a given bootstrap methods attribute. + * Bootstrap methods to be added must have been filled out beforehand. + * + * @author Eric Lafortune + */ +public class BootstrapMethodsAttributeEditor +{ + private BootstrapMethodsAttribute targetBootstrapMethodsAttribute; + + + /** + * Creates a new BootstrapMethodsAttributeEditor that will edit bootstrap + * methods in the given bootstrap methods attribute. + */ + public BootstrapMethodsAttributeEditor(BootstrapMethodsAttribute targetBootstrapMethodsAttribute) + { + this.targetBootstrapMethodsAttribute = targetBootstrapMethodsAttribute; + } + + + /** + * Adds a given bootstrap method to the bootstrap methods attribute. + * @return the index of the bootstrap method. + */ + public int addBootstrapMethodInfo(BootstrapMethodInfo bootstrapMethodInfo) + { + targetBootstrapMethodsAttribute.bootstrapMethods = + (BootstrapMethodInfo[])ArrayUtil.add(targetBootstrapMethodsAttribute.bootstrapMethods, + targetBootstrapMethodsAttribute.u2bootstrapMethodsCount, + bootstrapMethodInfo); + + return targetBootstrapMethodsAttribute.u2bootstrapMethodsCount++; + } +}
\ No newline at end of file diff --git a/src/proguard/classfile/editor/BridgeMethodFixer.java b/src/proguard/classfile/editor/BridgeMethodFixer.java index 2f1120d..5699b8e 100644 --- a/src/proguard/classfile/editor/BridgeMethodFixer.java +++ b/src/proguard/classfile/editor/BridgeMethodFixer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,12 +23,12 @@ 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.RefConstant; import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.instruction.*; import proguard.classfile.instruction.visitor.InstructionVisitor; -import proguard.classfile.util.*; -import proguard.classfile.visitor.*; +import proguard.classfile.util.SimplifiedVisitor; +import proguard.classfile.visitor.MemberVisitor; /** * This MemberVisitor fixes all inappropriate bridge access flags of the @@ -57,7 +57,7 @@ implements MemberVisitor, public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { - if ((programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_BRIDGE) != 0) + if ((programMethod.getAccessFlags() & ClassConstants.ACC_BRIDGE) != 0) { programMethod.attributesAccept(programClass, this); } @@ -101,7 +101,7 @@ implements MemberVisitor, } // Clear the bridge flag. - ((ProgramMethod)method).u2accessFlags &= ~ClassConstants.INTERNAL_ACC_BRIDGE; + ((ProgramMethod)method).u2accessFlags &= ~ClassConstants.ACC_BRIDGE; } break; } diff --git a/src/proguard/classfile/editor/ClassEditor.java b/src/proguard/classfile/editor/ClassEditor.java index 7703c9d..4d9055b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 9875a29..c514471 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 ed0b5b1..7ebe12e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 1f8b396..0570084 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -173,8 +173,11 @@ implements ClassVisitor, String newDescriptor = newDescriptor(descriptor, libraryMethod.referencedClasses); - // Update the descriptor. - libraryMethod.descriptor = newDescriptor; + if (!descriptor.equals(newDescriptor)) + { + // Update the descriptor. + libraryMethod.descriptor = newDescriptor; + } } @@ -200,7 +203,12 @@ implements ClassVisitor, // Update the String entry if required. if (!newInternalClassName.equals(internalClassName)) { - String newExternalClassName = ClassUtil.externalClassName(newInternalClassName); + // Only convert to an external class name if the original was + // an external class name too. + String newExternalClassName = + externalClassName.indexOf(JavaConstants.PACKAGE_SEPARATOR) >= 0 ? + ClassUtil.externalClassName(newInternalClassName) : + newInternalClassName; // Refer to a new Utf8 entry. stringConstant.u2stringIndex = @@ -210,6 +218,24 @@ implements ClassVisitor, } + public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + { + // Has the descriptor changed? + String descriptor = invokeDynamicConstant.getType(clazz); + String newDescriptor = newDescriptor(descriptor, + invokeDynamicConstant.referencedClasses); + + if (!descriptor.equals(newDescriptor)) + { + String name = invokeDynamicConstant.getName(clazz); + + // Refer to a new NameAndType entry. + invokeDynamicConstant.u2nameAndTypeIndex = + new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(name, newDescriptor); + } + } + + public void visitClassConstant(Clazz clazz, ClassConstant classConstant) { // Do we know the referenced class? @@ -228,6 +254,23 @@ implements ClassVisitor, } } + + public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) + { + // Has the descriptor changed? + String descriptor = methodTypeConstant.getType(clazz); + String newDescriptor = newDescriptor(descriptor, + methodTypeConstant.referencedClasses); + + if (!descriptor.equals(newDescriptor)) + { + // Update the descriptor. + methodTypeConstant.u2descriptorIndex = + new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newDescriptor); + } + } + + // Implementations for AttributeVisitor. public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} @@ -263,13 +306,14 @@ implements ClassVisitor, public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) { - // Compute the new signature. - String signature = clazz.getString(signatureAttribute.u2signatureIndex); + // Has the signature changed? + String signature = signatureAttribute.getSignature(clazz); String newSignature = newDescriptor(signature, signatureAttribute.referencedClasses); if (!signature.equals(newSignature)) { + // Update the signature. signatureAttribute.u2signatureIndex = new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature); } @@ -308,7 +352,7 @@ implements ClassVisitor, innerNameIndex != 0) { String newInnerName = clazz.getClassName(innerClassIndex); - int index = newInnerName.lastIndexOf(ClassConstants.INTERNAL_INNER_CLASS_SEPARATOR); + int index = newInnerName.lastIndexOf(ClassConstants.INNER_CLASS_SEPARATOR); if (index >= 0) { innerClassesInfo.u2innerNameIndex = @@ -323,7 +367,7 @@ implements ClassVisitor, public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) { // Has the descriptor changed? - String descriptor = clazz.getString(localVariableInfo.u2descriptorIndex); + String descriptor = localVariableInfo.getDescriptor(clazz); String newDescriptor = newDescriptor(descriptor, localVariableInfo.referencedClass); @@ -340,12 +384,13 @@ implements ClassVisitor, public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) { // Has the signature changed? - String signature = clazz.getString(localVariableTypeInfo.u2signatureIndex); + String signature = localVariableTypeInfo.getSignature(clazz); String newSignature = newDescriptor(signature, localVariableTypeInfo.referencedClasses); if (!signature.equals(newSignature)) { + // Update the signature. localVariableTypeInfo.u2signatureIndex = new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature); } @@ -355,14 +400,14 @@ implements ClassVisitor, public void visitAnnotation(Clazz clazz, Annotation annotation) { - // Compute the new type name. - String typeName = clazz.getString(annotation.u2typeIndex); + // Has the type changed? + String typeName = annotation.getType(clazz); String newTypeName = newDescriptor(typeName, annotation.referencedClasses); if (!typeName.equals(newTypeName)) { - // Refer to a new Utf8 entry. + // Update the type. annotation.u2typeIndex = new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newTypeName); } @@ -381,14 +426,14 @@ implements ClassVisitor, public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) { - // Compute the new type name. - String typeName = clazz.getString(enumConstantElementValue.u2typeNameIndex); + // Has the type name chamged? + String typeName = enumConstantElementValue.getTypeName(clazz); String newTypeName = newDescriptor(typeName, enumConstantElementValue.referencedClasses); if (!typeName.equals(newTypeName)) { - // Refer to a new Utf8 entry. + // Update the type name. enumConstantElementValue.u2typeNameIndex = new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newTypeName); } @@ -397,14 +442,14 @@ implements ClassVisitor, public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) { - // Compute the new class name. - String className = clazz.getString(classElementValue.u2classInfoIndex); + // Has the class info changed? + String className = classElementValue.getClassName(clazz); String newClassName = newDescriptor(className, classElementValue.referencedClasses); if (!className.equals(newClassName)) { - // Refer to a new Utf8 entry. + // Update the class info. classElementValue.u2classInfoIndex = new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newClassName); } @@ -492,7 +537,7 @@ implements ClassVisitor, if (isInnerClassName) { newClassName = - newClassName.substring(newClassName.lastIndexOf(ClassConstants.INTERNAL_INNER_CLASS_SEPARATOR)+1); + newClassName.substring(newClassName.lastIndexOf(ClassConstants.INNER_CLASS_SEPARATOR)+1); } newDescriptorBuffer.append(newClassName); @@ -508,8 +553,8 @@ implements ClassVisitor, */ private String newUniqueMemberName(String name, String descriptor) { - return name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ? - ClassConstants.INTERNAL_METHOD_NAME_INIT : + return name.equals(ClassConstants.METHOD_NAME_INIT) ? + ClassConstants.METHOD_NAME_INIT : name + ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode())); } @@ -532,13 +577,13 @@ implements ClassVisitor, String newClassName = referencedClass.getName(); // Is it an array type? - if (className.charAt(0) == ClassConstants.INTERNAL_TYPE_ARRAY) + if (className.charAt(0) == ClassConstants.TYPE_ARRAY) { // Add the array prefixes and suffix "[L...;". newClassName = - className.substring(0, className.indexOf(ClassConstants.INTERNAL_TYPE_CLASS_START)+1) + + className.substring(0, className.indexOf(ClassConstants.TYPE_CLASS_START)+1) + newClassName + - ClassConstants.INTERNAL_TYPE_CLASS_END; + ClassConstants.TYPE_CLASS_END; } return newClassName; diff --git a/src/proguard/classfile/editor/CodeAttributeComposer.java b/src/proguard/classfile/editor/CodeAttributeComposer.java index c59b712..eaa8015 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -60,6 +60,7 @@ implements AttributeVisitor, private static final int INVALID = -1; + private final boolean allowExternalBranchTargets; private final boolean allowExternalExceptionHandlers; private final boolean shrinkInstructions; @@ -85,17 +86,21 @@ implements AttributeVisitor, /** - * Creates a new CodeAttributeComposer that doesn't allow external exception - * handlers and that automatically shrinks instructions. + * Creates a new CodeAttributeComposer that doesn't allow external branch + * targets or exception handlers and that automatically shrinks + * instructions. */ public CodeAttributeComposer() { - this(false, true); + this(false, false, true); } /** * Creates a new CodeAttributeComposer. + * @param allowExternalBranchTargets specifies whether branch targets + * can lie outside the code fragment + * of the branch instructions. * @param allowExternalExceptionHandlers specifies whether exception * handlers can lie outside the code * fragment in which exceptions are @@ -104,9 +109,11 @@ implements AttributeVisitor, * should automatically be shrunk * before being written. */ - public CodeAttributeComposer(boolean allowExternalExceptionHandlers, + public CodeAttributeComposer(boolean allowExternalBranchTargets, + boolean allowExternalExceptionHandlers, boolean shrinkInstructions) { + this.allowExternalBranchTargets = allowExternalBranchTargets; this.allowExternalExceptionHandlers = allowExternalExceptionHandlers; this.shrinkInstructions = shrinkInstructions; } @@ -122,7 +129,9 @@ implements AttributeVisitor, exceptionTableLength = 0; level = -1; - instructionWriter.reset(ClassConstants.TYPICAL_CODE_LENGTH); + // Make sure the instruction writer has at least the same buffer size + // as the local arrays. + instructionWriter.reset(code.length); } @@ -362,9 +371,6 @@ implements AttributeVisitor, instructionOffset, instructionWriter); //instruction.write(code, codeLength); - - // Don't remap this instruction again. - oldInstructionOffsets[instructionOffset] = -1; } // Continue remapping at the next instruction offset. @@ -532,21 +538,48 @@ implements AttributeVisitor, public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) { - // Adjust the branch offset. - branchInstruction.branchOffset = newBranchOffset(offset, - branchInstruction.branchOffset); + try + { + // Adjust the branch offset. + branchInstruction.branchOffset = + newBranchOffset(offset, branchInstruction.branchOffset); + + // Don't remap this instruction again. + oldInstructionOffsets[offset] = -1; + } + catch (IllegalArgumentException e) + { + if (level == 0 || !allowExternalBranchTargets) + { + throw e; + } + } } public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction) { - // Adjust the default jump offset. - switchInstruction.defaultOffset = newBranchOffset(offset, - switchInstruction.defaultOffset); + try + { + // TODO: We're assuming we can adjust no offsets or all offsets at once. + // Adjust the default jump offset. + switchInstruction.defaultOffset = + newBranchOffset(offset, switchInstruction.defaultOffset); + + // Adjust the jump offsets. + updateJumpOffsets(offset, + switchInstruction.jumpOffsets); - // Adjust the jump offsets. - updateJumpOffsets(offset, - switchInstruction.jumpOffsets); + // Don't remap this instruction again. + oldInstructionOffsets[offset] = -1; + } + catch (IllegalArgumentException e) + { + if (level == 0 || !allowExternalBranchTargets) + { + throw e; + } + } } @@ -719,8 +752,10 @@ implements AttributeVisitor, int oldInstructionOffset = oldInstructionOffsets[newInstructionOffset]; + // For ordinary branch instructions, we can compute the offset + // relative to the instruction itself. return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - - newInstructionOffset(oldInstructionOffset); + newInstructionOffset; } diff --git a/src/proguard/classfile/editor/CodeAttributeEditor.java b/src/proguard/classfile/editor/CodeAttributeEditor.java index 337e0d4..41b7471 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,10 @@ package proguard.classfile.editor; import proguard.classfile.*; import proguard.classfile.attribute.*; +import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.target.*; +import proguard.classfile.attribute.annotation.target.visitor.*; +import proguard.classfile.attribute.annotation.visitor.TypeAnnotationVisitor; import proguard.classfile.attribute.preverification.*; import proguard.classfile.attribute.preverification.visitor.*; import proguard.classfile.attribute.visitor.*; @@ -47,7 +51,10 @@ implements AttributeVisitor, VerificationTypeVisitor, LineNumberInfoVisitor, LocalVariableInfoVisitor, - LocalVariableTypeInfoVisitor + LocalVariableTypeInfoVisitor, + TypeAnnotationVisitor, + TargetInfoVisitor, + LocalVariableTargetElementVisitor { //* private static final boolean DEBUG = false; @@ -179,7 +186,6 @@ implements AttributeVisitor, modified = true; simple = false; - } @@ -206,7 +212,6 @@ implements AttributeVisitor, modified = true; simple = false; - } @@ -512,6 +517,12 @@ implements AttributeVisitor, } + public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) + { + typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this); + } + + /** * Checks if it is possible to modifies the given code without having to * update any offsets. @@ -840,9 +851,9 @@ implements AttributeVisitor, public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) { - // Adjust the branch offset. - branchInstruction.branchOffset = newBranchOffset(offset, - branchInstruction.branchOffset); + // Update the branch offset, relative to the precise new offset. + branchInstruction.branchOffset = + newBranchOffset(offset, branchInstruction.branchOffset, newOffset); // Write out the instruction. instructionWriter.visitBranchInstruction(clazz, @@ -857,13 +868,14 @@ implements AttributeVisitor, public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction) { - // Adjust the default jump offset. - tableSwitchInstruction.defaultOffset = newBranchOffset(offset, - tableSwitchInstruction.defaultOffset); + // Update the default jump offset, relative to the precise new offset. + tableSwitchInstruction.defaultOffset = + newBranchOffset(offset, tableSwitchInstruction.defaultOffset, newOffset); - // Adjust the jump offsets. + // Update the jump offsets, relative to the precise new offset. newJumpOffsets(offset, - tableSwitchInstruction.jumpOffsets); + tableSwitchInstruction.jumpOffsets, + newOffset); // Write out the instruction. instructionWriter.visitTableSwitchInstruction(clazz, @@ -878,13 +890,14 @@ implements AttributeVisitor, public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) { - // Adjust the default jump offset. - lookUpSwitchInstruction.defaultOffset = newBranchOffset(offset, - lookUpSwitchInstruction.defaultOffset); + // Update the default jump offset, relative to the precise new offset. + lookUpSwitchInstruction.defaultOffset = + newBranchOffset(offset, lookUpSwitchInstruction.defaultOffset, newOffset); - // Adjust the jump offsets. + // Update the jump offsets, relative to the precise new offset. newJumpOffsets(offset, - lookUpSwitchInstruction.jumpOffsets); + lookUpSwitchInstruction.jumpOffsets, + newOffset); // Write out the instruction. instructionWriter.visitLookUpSwitchInstruction(clazz, @@ -901,8 +914,8 @@ implements AttributeVisitor, public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) { - // Update the code offsets. Note that the instruction offset map also has - // an entry for the first offset after the code, for u2endPC. + // 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 = newInstructionOffset(exceptionInfo.u2startPC); exceptionInfo.u2endPC = newInstructionOffset(exceptionInfo.u2endPC); exceptionInfo.u2handlerPC = newInstructionOffset(exceptionInfo.u2handlerPC); @@ -988,12 +1001,9 @@ implements AttributeVisitor, public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) { // 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; + // Be careful to update the length first. + localVariableInfo.u2length = newBranchOffset(localVariableInfo.u2startPC, localVariableInfo.u2length); + localVariableInfo.u2startPC = newInstructionOffset(localVariableInfo.u2startPC); } @@ -1002,41 +1012,99 @@ implements AttributeVisitor, public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) { // Update the code offset and length. - int newStartPC = newInstructionOffset(localVariableTypeInfo.u2startPC); - int newEndPC = newInstructionOffset(localVariableTypeInfo.u2startPC + - localVariableTypeInfo.u2length); + // Be careful to update the length first. + localVariableTypeInfo.u2length = newBranchOffset(localVariableTypeInfo.u2startPC, localVariableTypeInfo.u2length); + localVariableTypeInfo.u2startPC = newInstructionOffset(localVariableTypeInfo.u2startPC); + } + + + // Implementations for TypeAnnotationVisitor. + + public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) + { + // Update all local variable targets. + typeAnnotation.targetInfoAccept(clazz, this); + } + + + // Implementations for TargetInfoVisitor. + + public void visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo) {} + - localVariableTypeInfo.u2length = newEndPC - newStartPC; - localVariableTypeInfo.u2startPC = newStartPC; + public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) + { + // Update the offsets of the variables. + localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this); + } + + + public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo) + { + // Update the offset. + offsetTargetInfo.u2offset = newInstructionOffset(offsetTargetInfo.u2offset); + } + + + // Implementations for LocalVariableTargetElementVisitor. + + public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement) + { + // Update the variable start offset and length. + // Be careful to update the length first. + localVariableTargetElement.u2length = newBranchOffset(localVariableTargetElement.u2startPC, localVariableTargetElement.u2length); + localVariableTargetElement.u2startPC = newInstructionOffset(localVariableTargetElement.u2startPC); } // Small utility methods. /** - * Adjusts the given jump offsets for the instruction at the given offset. + * Updates the given jump offsets for the instruction at the given offset, + * relative to the given new offset. */ - private void newJumpOffsets(int oldInstructionOffset, int[] oldJumpOffsets) + private void newJumpOffsets(int oldInstructionOffset, + int[] oldJumpOffsets, + int newInstructionOffset) { for (int index = 0; index < oldJumpOffsets.length; index++) { - oldJumpOffsets[index] = newBranchOffset(oldInstructionOffset, oldJumpOffsets[index]); + oldJumpOffsets[index] = newBranchOffset(oldInstructionOffset, + oldJumpOffsets[index], + newInstructionOffset); } } /** * Computes the new branch offset for the instruction at the given offset - * with the given branch offset. + * with the given branch offset, relative to the new instruction (block) + * offset. + */ + private int newBranchOffset(int oldInstructionOffset, + int oldBranchOffset) + { + return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - + newInstructionOffset(oldInstructionOffset); + } + + + /** + * Computes the new branch offset for the instruction at the given offset + * with the given branch offset, relative to the given new offset. */ - private int newBranchOffset(int oldInstructionOffset, int oldBranchOffset) + private int newBranchOffset(int oldInstructionOffset, + int oldBranchOffset, + int newInstructionOffset) { - return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - newOffset; + return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - + newInstructionOffset; } /** - * Computes the new instruction offset for the instruction at the given offset. + * Computes the new instruction offset for the instruction at the given + * offset. */ private int newInstructionOffset(int oldInstructionOffset) { diff --git a/src/proguard/classfile/editor/CodeAttributeEditorResetter.java b/src/proguard/classfile/editor/CodeAttributeEditorResetter.java index 8f767c7..88e700b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 476edd6..cd2a810 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -148,7 +148,7 @@ implements Comparable, ConstantVisitor } public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) - { + { result = Double.compare(doubleConstant.getValue(), ((DoubleConstant)otherConstant).getValue()); } @@ -172,11 +172,10 @@ implements Comparable, ConstantVisitor result = index < otherIndex ? -1 : index > otherIndex ? 1 : - (invokeDynamicConstant.getName(clazz) + ' ' + - invokeDynamicConstant.getType(clazz)) - .compareTo - (otherInvokeDynamicConstant.getName(clazz) + ' ' + - otherInvokeDynamicConstant.getType(clazz)); + compare(invokeDynamicConstant.getName(clazz), + invokeDynamicConstant.getType(clazz), + otherInvokeDynamicConstant.getName(clazz), + otherInvokeDynamicConstant.getType(clazz)); } public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) @@ -184,27 +183,27 @@ implements Comparable, ConstantVisitor MethodHandleConstant otherMethodHandleConstant = (MethodHandleConstant)otherConstant; int kind = methodHandleConstant.getReferenceKind(); - int otherKind = methodHandleConstant.getReferenceKind(); + int otherKind = otherMethodHandleConstant.getReferenceKind(); result = kind < otherKind ? -1 : kind > otherKind ? 1 : - (methodHandleConstant.getName(clazz) + ' ' + - methodHandleConstant.getType(clazz)) - .compareTo - (otherMethodHandleConstant.getName(clazz) + ' ' + - otherMethodHandleConstant.getType(clazz)); + compare(methodHandleConstant.getClassName(clazz), + methodHandleConstant.getName(clazz), + methodHandleConstant.getType(clazz), + otherMethodHandleConstant.getClassName(clazz), + otherMethodHandleConstant.getName(clazz), + otherMethodHandleConstant.getType(clazz)); } public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) { RefConstant otherRefConstant = (RefConstant)otherConstant; - result = (refConstant.getClassName(clazz) + ' ' + - refConstant.getName(clazz) + ' ' + - refConstant.getType(clazz)) - .compareTo - (otherRefConstant.getClassName(clazz) + ' ' + - otherRefConstant.getName(clazz) + ' ' + - otherRefConstant.getType(clazz)); + result = compare(refConstant.getClassName(clazz), + refConstant.getName(clazz), + refConstant.getType(clazz), + otherRefConstant.getClassName(clazz), + otherRefConstant.getName(clazz), + otherRefConstant.getType(clazz)); } public void visitClassConstant(Clazz clazz, ClassConstant classConstant) @@ -223,11 +222,10 @@ implements Comparable, ConstantVisitor public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) { NameAndTypeConstant otherNameAndTypeConstant = (NameAndTypeConstant)otherConstant; - result = (nameAndTypeConstant.getName(clazz) + ' ' + - nameAndTypeConstant.getType(clazz)) - .compareTo - (otherNameAndTypeConstant.getName(clazz) + ' ' + - otherNameAndTypeConstant.getType(clazz)); + result = compare(nameAndTypeConstant.getName(clazz), + nameAndTypeConstant.getType(clazz), + otherNameAndTypeConstant.getName(clazz), + otherNameAndTypeConstant.getType(clazz)); } @@ -246,4 +244,33 @@ implements Comparable, ConstantVisitor { return this.getClass().hashCode(); } + + + // Small utility methods. + + /** + * Compares the given two pairs of strings. + */ + private int compare(String string1a, String string1b, + String string2a, String string2b) + { + int comparison; + return + (comparison = string1a.compareTo(string2a)) != 0 ? comparison : + string1b.compareTo(string2b); + } + + + /** + * Compares the given two triplets of strings. + */ + private int compare(String string1a, String string1b, String string1c, + String string2a, String string2b, String string2c) + { + int comparison; + return + (comparison = string1a.compareTo(string2a)) != 0 ? comparison : + (comparison = string1b.compareTo(string2b)) != 0 ? comparison : + string1c.compareTo(string2c); + } } diff --git a/src/proguard/classfile/editor/ConstantAdder.java b/src/proguard/classfile/editor/ConstantAdder.java index 9d20199..9f326ad 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,20 +21,24 @@ package proguard.classfile.editor; import proguard.classfile.*; +import proguard.classfile.attribute.*; 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 * of a given target class. * + * Bootstrap methods attributes are automatically updated for invokedynamic + * constants. + * * @author Eric Lafortune */ public class ConstantAdder implements ConstantVisitor { - private final ConstantPoolEditor constantPoolEditor; + private final ConstantPoolEditor constantPoolEditor; + private final BootstrapMethodsAttributeAdder bootstrapMethodsAttributeAdder; private int constantIndex; @@ -45,7 +49,8 @@ implements ConstantVisitor */ public ConstantAdder(ProgramClass targetClass) { - constantPoolEditor = new ConstantPoolEditor(targetClass); + constantPoolEditor = new ConstantPoolEditor(targetClass); + bootstrapMethodsAttributeAdder = new BootstrapMethodsAttributeAdder(targetClass); } @@ -131,7 +136,14 @@ implements ConstantVisitor public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) { - // First add the name and type constant. + // Find the bootstrap methods attribute. + AttributesEditor attributesEditor = + new AttributesEditor((ProgramClass)clazz, false); + + BootstrapMethodsAttribute bootstrapMethodsAttribute = + (BootstrapMethodsAttribute)attributesEditor.findAttribute(ClassConstants.ATTR_BootstrapMethods); + + // Add the name and type constant. clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this); // Copy the referenced classes. @@ -145,9 +157,13 @@ implements ConstantVisitor referencedClasses.length); } + bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz, + invokeDynamicConstant.getBootstrapMethodAttributeIndex(), + bootstrapMethodsAttributeAdder); + // Then add the actual invoke dynamic constant. constantIndex = - constantPoolEditor.addInvokeDynamicConstant(invokeDynamicConstant.getBootstrapMethodAttributeIndex(), + constantPoolEditor.addInvokeDynamicConstant(bootstrapMethodsAttributeAdder.getBootstrapMethodIndex(), constantIndex, referencedClassesCopy); } diff --git a/src/proguard/classfile/editor/ConstantPoolEditor.java b/src/proguard/classfile/editor/ConstantPoolEditor.java index 7adbc44..23f34fe 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/ConstantPoolRemapper.java b/src/proguard/classfile/editor/ConstantPoolRemapper.java index eaf7653..e033c30 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -53,6 +53,7 @@ implements ClassVisitor, InstructionVisitor, StackMapFrameVisitor, VerificationTypeVisitor, + ParameterInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, @@ -333,6 +334,16 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + methodParametersAttribute.u2attributeNameIndex = + remapConstantIndex(methodParametersAttribute.u2attributeNameIndex); + + // Remap the constant pool references of the parameter information. + methodParametersAttribute.parametersAccept(clazz, method, this); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { exceptionsAttribute.u2attributeNameIndex = @@ -552,6 +563,15 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + parameterInfo.u2nameIndex = + remapConstantIndex(parameterInfo.u2nameIndex); + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -569,7 +589,7 @@ implements ClassVisitor, { localVariableTypeInfo.u2nameIndex = remapConstantIndex(localVariableTypeInfo.u2nameIndex); - localVariableTypeInfo.u2signatureIndex = + localVariableTypeInfo.u2signatureIndex = remapConstantIndex(localVariableTypeInfo.u2signatureIndex); } @@ -637,8 +657,6 @@ implements ClassVisitor, } - // Small utility methods. - /** * Remaps all constant pool indices in the given array. */ @@ -650,6 +668,8 @@ implements ClassVisitor, } } + // Small utility methods. + /** * Returns the new constant pool index of the entry at the @@ -657,6 +677,12 @@ implements ClassVisitor, */ private int remapConstantIndex(int constantIndex) { - return constantIndexMap[constantIndex]; + int remappedConstantIndex = constantIndexMap[constantIndex]; + if (remappedConstantIndex < 0) + { + throw new IllegalArgumentException("Can't remap constant index ["+constantIndex+"]"); + } + + return remappedConstantIndex; } } diff --git a/src/proguard/classfile/editor/ConstantPoolShrinker.java b/src/proguard/classfile/editor/ConstantPoolShrinker.java index ee309a0..0172321 100644 --- a/src/proguard/classfile/editor/ConstantPoolShrinker.java +++ b/src/proguard/classfile/editor/ConstantPoolShrinker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -52,6 +52,7 @@ implements ClassVisitor, ExceptionInfoVisitor, StackMapFrameVisitor, VerificationTypeVisitor, + ParameterInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, @@ -251,6 +252,15 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + markConstant(clazz, methodParametersAttribute.u2attributeNameIndex); + + // Mark the constant pool entries referenced by the parameter information. + methodParametersAttribute.parametersAccept(clazz, method, this); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { markConstant(clazz, exceptionsAttribute.u2attributeNameIndex); @@ -405,6 +415,14 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + markConstant(clazz, parameterInfo.u2nameIndex); + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -554,11 +572,10 @@ implements ClassVisitor, // 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. + // Is the constant being used? Don't update the flag if this is the + // second half of a long entry. if (constant != null) { isUsed = isUsed(constant); @@ -566,8 +583,17 @@ implements ClassVisitor, if (isUsed) { + // Remember the new index. + constantIndexMap[index] = counter; + + // Shift the constant pool entry. constantPool[counter++] = constant; } + else + { + // Remember an invalid index. + constantIndexMap[index] = -1; + } } // Clear the remaining constant pool elements. diff --git a/src/proguard/classfile/editor/ConstantPoolSorter.java b/src/proguard/classfile/editor/ConstantPoolSorter.java index b578624..742bed2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/ElementValueAdder.java b/src/proguard/classfile/editor/ElementValueAdder.java index 9c8b3f9..5a99b01 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 57671e6..c4add27 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.editor; -import proguard.classfile.*; +import proguard.classfile.ProgramClass; import proguard.classfile.attribute.annotation.*; /** diff --git a/src/proguard/classfile/editor/ExceptionAdder.java b/src/proguard/classfile/editor/ExceptionAdder.java index 152a065..2ba0bb6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 c1c20fa..4798f84 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 98bb79e..8dd2e3c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 index 5a5e8a5..fdfdce5 100644 --- a/src/proguard/classfile/editor/InnerClassesAccessFixer.java +++ b/src/proguard/classfile/editor/InnerClassesAccessFixer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -21,12 +21,12 @@ package proguard.classfile.editor; import proguard.classfile.*; -import proguard.classfile.attribute.visitor.InnerClassesInfoVisitor; import proguard.classfile.attribute.InnerClassesInfo; +import proguard.classfile.attribute.visitor.InnerClassesInfoVisitor; import proguard.classfile.constant.*; import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.*; -import proguard.classfile.visitor.*; +import proguard.classfile.visitor.ClassVisitor; /** * This InnerClassesInfoVisitor fixes the inner class access flags of the diff --git a/src/proguard/classfile/editor/InstructionAdder.java b/src/proguard/classfile/editor/InstructionAdder.java index 422a348..4a20e59 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +21,9 @@ package proguard.classfile.editor; import proguard.classfile.*; -import proguard.classfile.attribute.*; -import proguard.classfile.instruction.visitor.InstructionVisitor; +import proguard.classfile.attribute.CodeAttribute; import proguard.classfile.instruction.*; +import proguard.classfile.instruction.visitor.InstructionVisitor; import proguard.classfile.util.SimplifiedVisitor; /** diff --git a/src/proguard/classfile/editor/InstructionWriter.java b/src/proguard/classfile/editor/InstructionWriter.java index c4a9b09..cafdd87 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/InterfaceAdder.java b/src/proguard/classfile/editor/InterfaceAdder.java index 1ad67dc..a7113b4 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +21,6 @@ package proguard.classfile.editor; import proguard.classfile.*; -import proguard.classfile.attribute.*; -import proguard.classfile.attribute.annotation.*; -import proguard.classfile.attribute.preverification.*; import proguard.classfile.constant.ClassConstant; import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.SimplifiedVisitor; diff --git a/src/proguard/classfile/editor/InterfaceDeleter.java b/src/proguard/classfile/editor/InterfaceDeleter.java new file mode 100644 index 0000000..6fd22b6 --- /dev/null +++ b/src/proguard/classfile/editor/InterfaceDeleter.java @@ -0,0 +1,190 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.Utf8Constant; +import proguard.classfile.util.*; +import proguard.classfile.visitor.ClassVisitor; + +import java.util.Arrays; + +/** + * This ClassVisitor removes specified interfaces from the classes and class + * signatures that it visits. + * + * @author Eric Lafortune + */ +public class InterfaceDeleter +extends SimplifiedVisitor +implements ClassVisitor, + AttributeVisitor +{ + private static final boolean DEBUG = false; + + + private final boolean[] delete; + + + /** + * Creates a new InterfaceDeleter to remove the specified interfaces. + * @param delete an array that corresponds to the interfaces of a class + * and that specifies the ones to be removed. + */ + public InterfaceDeleter(boolean[] delete) + { + this.delete = delete; + } + + + // Implementations for ClassVisitor. + + public void visitProgramClass(ProgramClass programClass) + { + int[] interfaces = programClass.u2interfaces; + int interfacesCount = programClass.u2interfacesCount; + + if (DEBUG) + { + System.out.println("InterfaceDeleter: "+programClass.getName()+" ("+interfacesCount+" interfaces)"); + } + + // Copy the interfaces that aren't deleted. + int newInterfacesCount = 0; + for (int index = 0; index < interfacesCount; index++) + { + if (DEBUG) + { + System.out.println("InterfaceDeleter: "+(delete[index]?"- ":"+ ")+programClass.getInterfaceName(index)); + } + + if (!delete[index]) + { + interfaces[newInterfacesCount++] = interfaces[index]; + } + } + + // Update the signature. + if (newInterfacesCount < interfacesCount) + { + programClass.u2interfacesCount = newInterfacesCount; + + programClass.attributesAccept(this); + } + } + + + // Implementations for AttributeVisitor. + + public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + + + public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) + { + Clazz[] referencedClasses = signatureAttribute.referencedClasses; + if (referencedClasses != null) + { + // Process the generic definitions, superclass, and implemented + // interfaces. + InternalTypeEnumeration internalTypeEnumeration = + new InternalTypeEnumeration(signatureAttribute.getSignature(clazz)); + + // Recompose the signature types in a string buffer. + StringBuffer newSignatureBuffer = new StringBuffer(); + + // Also update the array with referenced classes. + int referencedClassIndex = 0; + int newReferencedClassIndex = 0; + + // Copy the variable type declarations and the super class type. + while (internalTypeEnumeration.hasMoreTypes()) + { + String internalType = internalTypeEnumeration.nextType(); + + // Append the type. + newSignatureBuffer.append(internalType); + + // Copy any referenced classes. + int classCount = + new DescriptorClassEnumeration(internalType).classCount(); + + for (int counter = 0; counter < classCount; counter++) + { + referencedClasses[newReferencedClassIndex++] = + referencedClasses[referencedClassIndex++]; + } + + if (DEBUG) + { + System.out.println("InterfaceDeleter: type = " + internalType + " (" + classCount + " referenced classes)"); + } + + if (ClassUtil.isInternalClassType(internalType)) + { + break; + } + } + + // Copy the interface types. + int index = 0; + while (internalTypeEnumeration.hasMoreTypes()) + { + String internalType = internalTypeEnumeration.nextType(); + + int classCount = + new DescriptorClassEnumeration(internalType).classCount(); + + if (DEBUG) + { + System.out.println("InterfaceDeleter: type " + (delete[index] ? "- " : "+ ") + internalType + " (" + classCount + " referenced classes)"); + } + + if (!delete[index++]) + { + // Append the type. + newSignatureBuffer.append(internalType); + + // Copy any referenced classes. + for (int counter = 0; counter < classCount; counter++) + { + referencedClasses[newReferencedClassIndex++] = + referencedClasses[referencedClassIndex++]; + } + } + else + { + referencedClassIndex += classCount; + } + } + + // Update the signature. + ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString()); + + // Clear the remaining referenced classes. + Arrays.fill(referencedClasses, + newReferencedClassIndex, + referencedClassIndex, + null); + } + } +} diff --git a/src/proguard/classfile/editor/InterfaceSorter.java b/src/proguard/classfile/editor/InterfaceSorter.java index 0d1f28c..a67b0a2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,12 +23,11 @@ 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.constant.Utf8Constant; import proguard.classfile.util.*; import proguard.classfile.visitor.ClassVisitor; -import java.util.*; +import java.util.Arrays; /** * This ClassVisitor sorts the interfaces of the program classes that it visits. @@ -52,27 +51,30 @@ implements ClassVisitor, // Sort the interfaces. Arrays.sort(interfaces, 0, interfacesCount); + // Update the signature. + programClass.attributesAccept(this); + // Remove any duplicate entries. - int newInterfacesCount = 0; - int previousInterfaceIndex = 0; - for (int index = 0; index < interfacesCount; index++) + boolean[] delete = null; + for (int index = 1; index < interfacesCount; index++) { - int interfaceIndex = interfaces[index]; - - // Isn't this a duplicate of the previous interface? - if (interfaceIndex != previousInterfaceIndex) + Clazz interfaceClass = programClass.getInterface(index); + if (interfaces[index] == interfaces[index - 1]) { - interfaces[newInterfacesCount++] = interfaceIndex; + // Lazily create the array. + if (delete == null) + { + delete = new boolean[interfacesCount]; + } - // Remember the interface. - previousInterfaceIndex = interfaceIndex; + delete[index] = true; } } - programClass.u2interfacesCount = newInterfacesCount; - - // Update the signature, if any - programClass.attributesAccept(this); + if (delete != null) + { + new InterfaceDeleter(delete).visitProgramClass(programClass); + } } } @@ -86,7 +88,7 @@ implements ClassVisitor, { // Process the generic definitions, superclass, and implemented // interfaces. - String signature = clazz.getString(signatureAttribute.u2signatureIndex); + String signature = signatureAttribute.getSignature(clazz); // Count the signature types. InternalTypeEnumeration internalTypeEnumeration = @@ -127,13 +129,7 @@ implements ClassVisitor, 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]); - } + newSignatureBuffer.append(internalTypes[index]); } String newSignature = newSignatureBuffer.toString(); diff --git a/src/proguard/classfile/editor/InterfacesEditor.java b/src/proguard/classfile/editor/InterfacesEditor.java index 8765e36..4de2b2b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,10 +20,8 @@ */ package proguard.classfile.editor; -import proguard.classfile.*; -import proguard.classfile.attribute.*; - -import java.util.Arrays; +import proguard.classfile.ProgramClass; +import proguard.util.ArrayUtil; /** * This class can add and delete interfaces to and from classes. References to @@ -54,22 +52,11 @@ public class InterfacesEditor // Is the interface not yet present? if (findInterfaceIndex(interfaceConstantIndex) < 0) { - int interfacesCount = targetClass.u2interfacesCount++; - int[] interfaces = targetClass.u2interfaces; - - // Is the array too small to contain the additional interface? - if (interfaces.length <= interfacesCount) - { - // Create a new array and copy the interfaces into it. - int[] newinterfaces = new int[interfacesCount + 1]; - System.arraycopy(interfaces, 0, newinterfaces, 0, interfacesCount); - interfaces = newinterfaces; - - targetClass.u2interfaces = interfaces; - } - // Append the interface. - interfaces[interfacesCount] = interfaceConstantIndex; + targetClass.u2interfaces = + ArrayUtil.add(targetClass.u2interfaces, + targetClass.u2interfacesCount++, + interfaceConstantIndex); } } @@ -112,9 +99,9 @@ public class InterfacesEditor for (int index = 0; index < interfacesCount; index++) { if (interfaces[index] == interfaceConstantIndex) - { - return index; - } + { + return index; + } } return -1; diff --git a/src/proguard/classfile/editor/LineNumberInfoAdder.java b/src/proguard/classfile/editor/LineNumberInfoAdder.java index e1bd14a..c53fc26 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,9 +20,9 @@ */ package proguard.classfile.editor; -import proguard.classfile.attribute.visitor.LineNumberInfoVisitor; -import proguard.classfile.attribute.*; import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.LineNumberInfoVisitor; /** * This LineNumberInfoVisitor adds all line numbers that it visits to the given diff --git a/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java b/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java index f712d46..5c2cdf3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 a270fcf..cfbb570 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,13 +20,13 @@ */ package proguard.classfile.editor; -import proguard.classfile.attribute.visitor.LocalVariableInfoVisitor; -import proguard.classfile.attribute.*; import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.LocalVariableInfoVisitor; /** - * This LocalVariableInfoVisitor adds all line numbers that it visits to the given - * target line number attribute. + * This LocalVariableInfoVisitor adds all local variables that it visits to the + * given target local variable table attribute. */ public class LocalVariableInfoAdder implements LocalVariableInfoVisitor @@ -36,8 +36,8 @@ implements LocalVariableInfoVisitor /** - * Creates a new LocalVariableInfoAdder that will copy line numbers into the - * given target line number table. + * Creates a new LocalVariableInfoAdder that will copy local variables + * into the given target local variable table. */ public LocalVariableInfoAdder(ProgramClass targetClass, LocalVariableTableAttribute targetLocalVariableTableAttribute) @@ -51,7 +51,7 @@ implements LocalVariableInfoVisitor public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) { - // Create a new line number. + // Create a new local variable. LocalVariableInfo newLocalVariableInfo = new LocalVariableInfo(localVariableInfo.u2startPC, localVariableInfo.u2length, diff --git a/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java b/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java index b9e601f..d26f937 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.classfile.editor; import proguard.classfile.attribute.*; +import proguard.util.ArrayUtil; /** * This class can add local variables to a given local variable table attribute. @@ -30,12 +31,12 @@ import proguard.classfile.attribute.*; */ public class LocalVariableTableAttributeEditor { - private LocalVariableTableAttribute targetLocalVariableTableAttribute; + private final LocalVariableTableAttribute targetLocalVariableTableAttribute; /** - * Creates a new LocalVariableTableAttributeEditor that will edit line numbers - * in the given line number table attribute. + * Creates a new LocalVariableTableAttributeEditor that will edit local + * variables in the given local variable table attribute. */ public LocalVariableTableAttributeEditor(LocalVariableTableAttribute targetLocalVariableTableAttribute) { @@ -48,20 +49,9 @@ public class LocalVariableTableAttributeEditor */ public void addLocalVariableInfo(LocalVariableInfo localVariableInfo) { - int localVariableTableLength = targetLocalVariableTableAttribute.u2localVariableTableLength; - LocalVariableInfo[] localVariableTable = targetLocalVariableTableAttribute.localVariableTable; - - // Make sure there is enough space for the new localVariableInfo. - if (localVariableTable.length <= localVariableTableLength) - { - targetLocalVariableTableAttribute.localVariableTable = new LocalVariableInfo[localVariableTableLength+1]; - System.arraycopy(localVariableTable, 0, - targetLocalVariableTableAttribute.localVariableTable, 0, - localVariableTableLength); - localVariableTable = targetLocalVariableTableAttribute.localVariableTable; - } - - // Add the localVariableInfo. - localVariableTable[targetLocalVariableTableAttribute.u2localVariableTableLength++] = localVariableInfo; + targetLocalVariableTableAttribute.localVariableTable = + (LocalVariableInfo[])ArrayUtil.add(targetLocalVariableTableAttribute.localVariableTable, + targetLocalVariableTableAttribute.u2localVariableTableLength++, + localVariableInfo); } }
\ No newline at end of file diff --git a/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java b/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java index bed1366..94a5f2a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,13 +20,13 @@ */ package proguard.classfile.editor; -import proguard.classfile.attribute.visitor.LocalVariableTypeInfoVisitor; -import proguard.classfile.attribute.*; import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.LocalVariableTypeInfoVisitor; /** - * This LocalVariableTypeInfoVisitor adds all line numbers that it visits to the given - * target line number attribute. + * This LocalVariableTypeInfoVisitor adds all local variable types that it + * visits to the given target local variable type attribute. */ public class LocalVariableTypeInfoAdder implements LocalVariableTypeInfoVisitor @@ -36,8 +36,8 @@ implements LocalVariableTypeInfoVisitor /** - * Creates a new LocalVariableTypeInfoAdder that will copy line numbers into the - * given target line number table. + * Creates a new LocalVariableTypeInfoAdder that will copy local variable + * types into the given target local variable type table. */ public LocalVariableTypeInfoAdder(ProgramClass targetClass, LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute) @@ -51,7 +51,7 @@ implements LocalVariableTypeInfoVisitor public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) { - // Create a new line number. + // Create a new local variable type. LocalVariableTypeInfo newLocalVariableTypeInfo = new LocalVariableTypeInfo(localVariableTypeInfo.u2startPC, localVariableTypeInfo.u2length, diff --git a/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java b/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java index 00f7ef3..724b7b0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.classfile.editor; import proguard.classfile.attribute.*; +import proguard.util.ArrayUtil; /** * This class can add local variables to a given local variable type table @@ -31,12 +32,12 @@ import proguard.classfile.attribute.*; */ public class LocalVariableTypeTableAttributeEditor { - private LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute; + private final LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute; /** - * Creates a new LocalVariableTypeTableAttributeEditor that will edit line numbers - * in the given line number table attribute. + * Creates a new LocalVariableTypeTableAttributeEditor that will edit local + * variable types in the given local variable type table attribute. */ public LocalVariableTypeTableAttributeEditor(LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute) { @@ -45,24 +46,13 @@ public class LocalVariableTypeTableAttributeEditor /** - * Adds a given line number to the line number table attribute. + * Adds a given local variable type to the local variable type table attribute. */ public void addLocalVariableTypeInfo(LocalVariableTypeInfo localVariableTypeInfo) { - int localVariableTypeTableLength = targetLocalVariableTypeTableAttribute.u2localVariableTypeTableLength; - LocalVariableTypeInfo[] localVariableTypeTable = targetLocalVariableTypeTableAttribute.localVariableTypeTable; - - // Make sure there is enough space for the new localVariableTypeInfo. - if (localVariableTypeTable.length <= localVariableTypeTableLength) - { - targetLocalVariableTypeTableAttribute.localVariableTypeTable = new LocalVariableTypeInfo[localVariableTypeTableLength+1]; - System.arraycopy(localVariableTypeTable, 0, - targetLocalVariableTypeTableAttribute.localVariableTypeTable, 0, - localVariableTypeTableLength); - localVariableTypeTable = targetLocalVariableTypeTableAttribute.localVariableTypeTable; - } - - // Add the localVariableTypeInfo. - localVariableTypeTable[targetLocalVariableTypeTableAttribute.u2localVariableTypeTableLength++] = localVariableTypeInfo; + targetLocalVariableTypeTableAttribute.localVariableTypeTable = + (LocalVariableTypeInfo[])ArrayUtil.add(targetLocalVariableTypeTableAttribute.localVariableTypeTable, + targetLocalVariableTypeTableAttribute.u2localVariableTypeTableLength++, + localVariableTypeInfo); } }
\ No newline at end of file diff --git a/src/proguard/classfile/editor/MemberAdder.java b/src/proguard/classfile/editor/MemberAdder.java index 811acae..2a93016 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -110,8 +110,8 @@ implements MemberVisitor // // Is the field private or static? // int targetAccessFlags = targetField.getAccessFlags(); // if ((targetAccessFlags & - // (ClassConstants.INTERNAL_ACC_PRIVATE | - // ClassConstants.INTERNAL_ACC_STATIC)) != 0) + // (ClassConstants.ACC_PRIVATE | + // ClassConstants.ACC_STATIC)) != 0) // { // if (DEBUG) // { @@ -192,7 +192,7 @@ implements MemberVisitor if (targetMethod != null) { // is this source method abstract? - if ((accessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0) + if ((accessFlags & ClassConstants.ACC_ABSTRACT) != 0) { // Keep the target method. if (DEBUG) @@ -206,7 +206,7 @@ implements MemberVisitor // Is the target method abstract? int targetAccessFlags = targetMethod.getAccessFlags(); - if ((targetAccessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0) + if ((targetAccessFlags & ClassConstants.ACC_ABSTRACT) != 0) { // Keep the abstract method, but update its contents, in order // to keep any references to it valid. @@ -217,7 +217,7 @@ implements MemberVisitor // Replace the access flags. targetMethod.u2accessFlags = - accessFlags & ~ClassConstants.INTERNAL_ACC_FINAL; + accessFlags & ~ClassConstants.ACC_FINAL; // Add and replace the attributes. programMethod.attributesAccept(programClass, @@ -249,7 +249,7 @@ implements MemberVisitor // Create a copy of the method. ProgramMethod newProgramMethod = - new ProgramMethod(accessFlags & ~ClassConstants.INTERNAL_ACC_FINAL, + new ProgramMethod(accessFlags & ~ClassConstants.ACC_FINAL, constantAdder.addConstant(programClass, programMethod.u2nameIndex), constantAdder.addConstant(programClass, programMethod.u2descriptorIndex), 0, @@ -287,8 +287,8 @@ implements MemberVisitor */ private String newUniqueMemberName(String name, String descriptor) { - return name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ? - ClassConstants.INTERNAL_METHOD_NAME_INIT : + return name.equals(ClassConstants.METHOD_NAME_INIT) ? + ClassConstants.METHOD_NAME_INIT : name + ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode())); } } diff --git a/src/proguard/classfile/editor/MemberReferenceFixer.java b/src/proguard/classfile/editor/MemberReferenceFixer.java index b623047..3a32963 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -271,7 +271,7 @@ implements ClassVisitor, Clazz referencedClass = classConstant.referencedClass; if (referencedClass != null) { - isInterfaceMethod = (referencedClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE) != 0; + isInterfaceMethod = (referencedClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) != 0; } } } diff --git a/src/proguard/classfile/editor/MethodInvocationFixer.java b/src/proguard/classfile/editor/MethodInvocationFixer.java index e457e63..81b33ea 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -92,7 +92,7 @@ implements AttributeVisitor, byte opcode = constantInstruction.opcode; // Is the method static? - if ((referencedMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0) + if ((referencedMethod.getAccessFlags() & ClassConstants.ACC_STATIC) != 0) { // But is it not a static invocation? if (opcode != InstructionConstants.OP_INVOKESTATIC) @@ -112,8 +112,8 @@ implements AttributeVisitor, } // Is the method private, or an instance initializer? - else if ((referencedMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_PRIVATE) != 0 || - referencedMethod.getName(referencedMethodClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + else if ((referencedMethod.getAccessFlags() & ClassConstants.ACC_PRIVATE) != 0 || + referencedMethod.getName(referencedMethodClass).equals(ClassConstants.METHOD_NAME_INIT)) { // But is it not a special invocation? if (opcode != InstructionConstants.OP_INVOKESPECIAL) @@ -133,7 +133,7 @@ implements AttributeVisitor, } // Is the method an interface method? - else if ((referencedClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE) != 0) + else if ((referencedClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) != 0) { int invokeinterfaceConstant = (ClassUtil.internalMethodParameterSize(referencedMethod.getDescriptor(referencedMethodClass), false)) << 8; @@ -234,7 +234,7 @@ implements AttributeVisitor, System.out.println(" Instruction = "+constantInstruction.toString(offset)); System.out.println(" -> Class = "+referencedClass); System.out.println(" Method = "+referencedMethod); - if ((referencedClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE) != 0) + if ((referencedClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) != 0) { System.out.println(" Parameter size = "+(ClassUtil.internalMethodParameterSize(referencedMethod.getDescriptor(referencedMethodClass), false))); } diff --git a/src/proguard/classfile/editor/NameAndTypeShrinker.java b/src/proguard/classfile/editor/NameAndTypeShrinker.java index 650f9ba..40181b2 100644 --- a/src/proguard/classfile/editor/NameAndTypeShrinker.java +++ b/src/proguard/classfile/editor/NameAndTypeShrinker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ 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; @@ -163,11 +162,10 @@ implements ClassVisitor, // 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. + // Is the constant being used? Don't update the flag if this is the + // second half of a long entry. if (constant != null) { isUsed = constant.getTag() != ClassConstants.CONSTANT_NameAndType || @@ -176,8 +174,17 @@ implements ClassVisitor, if (isUsed) { + // Remember the new index. + constantIndexMap[index] = counter; + + // Shift the constant pool entry. constantPool[counter++] = constant; } + else + { + // Remember an invalid index. + constantIndexMap[index] = -1; + } } // Clear the remaining constant pool elements. diff --git a/src/proguard/classfile/editor/NamedAttributeDeleter.java b/src/proguard/classfile/editor/NamedAttributeDeleter.java index 6aa5cdf..c02ba84 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,17 +21,23 @@ package proguard.classfile.editor; import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.AttributeVisitor; +import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.*; -import proguard.util.StringMatcher; /** * This ClassVisitor deletes attributes with a given name in the program - * classes that it visits. + * classes, fields, methods, or code attributes that it visits. * * @author Eric Lafortune */ -public class NamedAttributeDeleter implements ClassVisitor +public class NamedAttributeDeleter +extends SimplifiedVisitor +implements ClassVisitor, + MemberVisitor, + AttributeVisitor { private final String attributeName; @@ -51,4 +57,26 @@ public class NamedAttributeDeleter implements ClassVisitor { new AttributesEditor(programClass, false).deleteAttribute(attributeName); } + + + // Implementations for MemberVisitor. + + public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) {} + + + public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) + { + new AttributesEditor(programClass, programMember, false).deleteAttribute(attributeName); + } + + + // Implementations for AttributeVisitor. + + public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + + + public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) + { + new AttributesEditor((ProgramClass)clazz, (ProgramMember)method, codeAttribute, false).deleteAttribute(attributeName); + } }
\ No newline at end of file diff --git a/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java b/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java index 232747f..b7d29f7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.classfile.editor; import proguard.classfile.attribute.annotation.*; +import proguard.util.ArrayUtil; /** * This class can add annotations to a given parameter annotations attribute. @@ -48,24 +49,8 @@ public class ParameterAnnotationsAttributeEditor */ public void addAnnotation(int parameterIndex, Annotation annotation) { - int annotationsCount = targetParameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]; - Annotation[] annotations = targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex]; - - // Make sure there is enough space for the new annotation. - if (annotations == null || - annotations.length <= annotationsCount) - { - targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex] = new Annotation[annotationsCount+1]; - if (annotations != null) - { - System.arraycopy(annotations, 0, - targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex], 0, - annotationsCount); - } - annotations = targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex]; - } - - // Add the annotation. - annotations[targetParameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]++] = annotation; + ArrayUtil.add(targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex], + targetParameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]++, + annotation); } }
\ No newline at end of file diff --git a/src/proguard/classfile/editor/ParameterInfoAdder.java b/src/proguard/classfile/editor/ParameterInfoAdder.java new file mode 100644 index 0000000..50d35b2 --- /dev/null +++ b/src/proguard/classfile/editor/ParameterInfoAdder.java @@ -0,0 +1,62 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.ParameterInfoVisitor; + +/** + * This ParameterInfoVisitor adds all parameter information that it visits to + * the given target method parameters attribute. + */ +public class ParameterInfoAdder +implements ParameterInfoVisitor +{ + private final ConstantAdder constantAdder; + private final MethodParametersAttribute targetMethodParametersAttribute; + + + /** + * Creates a new ParameterInfoAdder that will copy parameter information + * into the given target method parameters attribute. + */ + public ParameterInfoAdder(ProgramClass targetClass, + MethodParametersAttribute targetMethodParametersAttribute) + { + this.constantAdder = new ConstantAdder(targetClass); + this.targetMethodParametersAttribute = targetMethodParametersAttribute; + } + + + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + // Create a new parameter. + ParameterInfo newParameterInfo = + new ParameterInfo(constantAdder.addConstant(clazz, parameterInfo.u2nameIndex), + parameterInfo.u2accessFlags); + + // Add it to the target. + targetMethodParametersAttribute.parameters[parameterIndex] = newParameterInfo; + } +}
\ No newline at end of file diff --git a/src/proguard/classfile/editor/StackSizeUpdater.java b/src/proguard/classfile/editor/StackSizeUpdater.java index d90b3d0..d49e53c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 717bb1c..d7f179a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 109152b..dc6de07 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/Utf8Shrinker.java b/src/proguard/classfile/editor/Utf8Shrinker.java index eda5826..35626d7 100644 --- a/src/proguard/classfile/editor/Utf8Shrinker.java +++ b/src/proguard/classfile/editor/Utf8Shrinker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.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.*; @@ -47,6 +46,7 @@ implements ClassVisitor, ConstantVisitor, AttributeVisitor, InnerClassesInfoVisitor, + ParameterInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, @@ -198,6 +198,15 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + markCpUtf8Entry(clazz, methodParametersAttribute.u2attributeNameIndex); + + // Mark the UTF-8 entries referenced by the parameter information. + methodParametersAttribute.parametersAccept(clazz, method, this); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { markCpUtf8Entry(clazz, exceptionsAttribute.u2attributeNameIndex); @@ -287,6 +296,17 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + if (parameterInfo.u2nameIndex != 0) + { + markCpUtf8Entry(clazz, parameterInfo.u2nameIndex); + } + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -430,11 +450,10 @@ implements ClassVisitor, // 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. + // Is the constant being used? Don't update the flag if this is the + // second half of a long entry. if (constant != null) { isUsed = constant.getTag() != ClassConstants.CONSTANT_Utf8 || @@ -443,8 +462,17 @@ implements ClassVisitor, if (isUsed) { + // Remember the new index. + constantIndexMap[index] = counter; + + // Shift the constant pool entry. constantPool[counter++] = constant; } + else + { + // Remember an invalid index. + constantIndexMap[index] = -1; + } } // Clear the remaining constant pool elements. diff --git a/src/proguard/classfile/editor/VariableCleaner.java b/src/proguard/classfile/editor/VariableCleaner.java index 63b7d4a..be67e05 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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/VariableEditor.java b/src/proguard/classfile/editor/VariableEditor.java index b5143b5..2fd5471 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/VariableRemapper.java b/src/proguard/classfile/editor/VariableRemapper.java index ca9d88a..1ca1cb5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,10 @@ package proguard.classfile.editor; import proguard.classfile.*; import proguard.classfile.attribute.*; +import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.target.*; +import proguard.classfile.attribute.annotation.target.visitor.*; +import proguard.classfile.attribute.annotation.visitor.TypeAnnotationVisitor; import proguard.classfile.attribute.visitor.*; import proguard.classfile.instruction.*; import proguard.classfile.instruction.visitor.InstructionVisitor; @@ -38,7 +42,10 @@ extends SimplifiedVisitor implements AttributeVisitor, InstructionVisitor, LocalVariableInfoVisitor, - LocalVariableTypeInfoVisitor + LocalVariableTypeInfoVisitor, + TypeAnnotationVisitor, + TargetInfoVisitor, + LocalVariableTargetElementVisitor { private static final boolean DEBUG = false; @@ -63,6 +70,22 @@ implements AttributeVisitor, public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + // Reorder the array with parameter information. + ParameterInfo[] oldParameters = methodParametersAttribute.parameters; + ParameterInfo[] newParameters = + new ParameterInfo[methodParametersAttribute.u1parametersCount]; + + for (int index = 0; index < methodParametersAttribute.u1parametersCount; index++) + { + newParameters[remapVariable(index)] = oldParameters[index]; + } + + methodParametersAttribute.parameters = newParameters; + } + + public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { if (DEBUG) @@ -103,6 +126,13 @@ implements AttributeVisitor, } + public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) + { + // Remap the variable references of local variable type annotations. + typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this); + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -121,6 +151,34 @@ implements AttributeVisitor, } + // Implementations for TypeAnnotationVisitor. + + public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) + { + typeAnnotation.targetInfoAccept(clazz, this); + } + + + // Implementations for TargetInfoVisitor. + + public void visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo) {} + + + public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) + { + localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this); + } + + + // Implementations for LocalVariableTargetElementVisitor. + + public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement) + { + localVariableTargetElement.u2index = + remapVariable(localVariableTargetElement.u2index); + } + + // Implementations for InstructionVisitor. public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} diff --git a/src/proguard/classfile/editor/VariableSizeUpdater.java b/src/proguard/classfile/editor/VariableSizeUpdater.java index 2feaa9d..f364f92 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/instruction/BranchInstruction.java b/src/proguard/classfile/instruction/BranchInstruction.java index f3a7080..8099186 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/instruction/ConstantInstruction.java b/src/proguard/classfile/instruction/ConstantInstruction.java index 42d1523..42db94f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/instruction/Instruction.java b/src/proguard/classfile/instruction/Instruction.java index 33e705d..ecdc05c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,214 @@ import proguard.classfile.instruction.visitor.InstructionVisitor; */ public abstract class Instruction { + // An array for marking instructions that may throw exceptions. + private static final boolean[] MAY_THROW_EXCEPTIONS = new boolean[] + { + false, // nop + false, // aconst_null + false, // iconst_m1 + false, // iconst_0 + false, // iconst_1 + false, // iconst_2 + false, // iconst_3 + false, // iconst_4 + false, // iconst_5 + false, // lconst_0 + false, // lconst_1 + false, // fconst_0 + false, // fconst_1 + false, // fconst_2 + false, // dconst_0 + false, // dconst_1 + false, // bipush + false, // sipush + false, // ldc + false, // ldc_w + false, // ldc2_w + false, // iload + false, // lload + false, // fload + false, // dload + false, // aload + false, // iload_0 + false, // iload_1 + false, // iload_2 + false, // iload_3 + false, // lload_0 + false, // lload_1 + false, // lload_2 + false, // lload_3 + false, // fload_0 + false, // fload_1 + false, // fload_2 + false, // fload_3 + false, // dload_0 + false, // dload_1 + false, // dload_2 + false, // dload_3 + false, // aload_0 + false, // aload_1 + false, // aload_2 + false, // aload_3 + true, // iaload + true, // laload + true, // faload + true, // daload + true, // aaload + true, // baload + true, // caload + true, // saload + false, // istore + false, // lstore + false, // fstore + false, // dstore + false, // astore + false, // istore_0 + false, // istore_1 + false, // istore_2 + false, // istore_3 + false, // lstore_0 + false, // lstore_1 + false, // lstore_2 + false, // lstore_3 + false, // fstore_0 + false, // fstore_1 + false, // fstore_2 + false, // fstore_3 + false, // dstore_0 + false, // dstore_1 + false, // dstore_2 + false, // dstore_3 + false, // astore_0 + false, // astore_1 + false, // astore_2 + false, // astore_3 + true, // iastore + true, // lastore + true, // fastore + true, // dastore + true, // aastore + true, // bastore + true, // castore + true, // sastore + false, // pop + false, // pop2 + false, // dup + false, // dup_x1 + false, // dup_x2 + false, // dup2 + false, // dup2_x1 + false, // dup2_x2 + false, // swap + false, // iadd + false, // ladd + false, // fadd + false, // dadd + false, // isub + false, // lsub + false, // fsub + false, // dsub + false, // imul + false, // lmul + false, // fmul + false, // dmul + true, // idiv + true, // ldiv + false, // fdiv + false, // ddiv + true, // irem + true, // lrem + false, // frem + false, // drem + false, // ineg + false, // lneg + false, // fneg + false, // dneg + false, // ishl + false, // lshl + false, // ishr + false, // lshr + false, // iushr + false, // lushr + false, // iand + false, // land + false, // ior + false, // lor + false, // ixor + false, // lxor + false, // iinc + false, // i2l + false, // i2f + false, // i2d + false, // l2i + false, // l2f + false, // l2d + false, // f2i + false, // f2l + false, // f2d + false, // d2i + false, // d2l + false, // d2f + false, // i2b + false, // i2c + false, // i2s + false, // lcmp + false, // fcmpl + false, // fcmpg + false, // dcmpl + false, // dcmpg + false, // ifeq + false, // ifne + false, // iflt + false, // ifge + false, // ifgt + false, // ifle + false, // ificmpeq + false, // ificmpne + false, // ificmplt + false, // ificmpge + false, // ificmpgt + false, // ificmple + false, // ifacmpeq + false, // ifacmpne + false, // goto + false, // jsr + false, // ret + false, // tableswitch + false, // lookupswitch + false, // ireturn + false, // lreturn + false, // freturn + false, // dreturn + false, // areturn + false, // return + true, // getstatic + true, // putstatic + true, // getfield + true, // putfield + true, // invokevirtual + true, // invokespecial + true, // invokestatic + true, // invokeinterface + true, // invokedynamic + true, // new + true, // newarray + true, // anewarray + true, // arraylength + true, // athrow + true, // checkcast + false, // instanceof + true, // monitorenter + true, // monitorexit + false, // wide + true, // multianewarray + false, // ifnull + false, // ifnonnull + false, // goto_w + false, // jsr_w + }; + + // An array for marking Category 2 instructions. private static final boolean[] IS_CATEGORY2 = new boolean[] { @@ -759,6 +967,15 @@ public abstract class Instruction /** + * Returns whether the instruction may throw exceptions. + */ + public boolean mayThrowExceptions() + { + return MAY_THROW_EXCEPTIONS[opcode & 0xff]; + } + + + /** * Returns whether the instruction is a Category 2 instruction. This means * that it operates on long or double arguments. */ diff --git a/src/proguard/classfile/instruction/InstructionConstants.java b/src/proguard/classfile/instruction/InstructionConstants.java index d8cbd98..0cc1928 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/instruction/InstructionFactory.java b/src/proguard/classfile/instruction/InstructionFactory.java index 89d498c..6e08141 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/instruction/InstructionUtil.java b/src/proguard/classfile/instruction/InstructionUtil.java index c6ae99b..f7d8888 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,27 +40,27 @@ public class InstructionUtil * <code>InstructionConstants.ARRAY_T_LONG</code>, * <code>InstructionConstants.ARRAY_T_FLOAT</code>, or * <code>InstructionConstants.ARRAY_T_DOUBLE</code>. - * @return <code>ClassConstants.INTERNAL_TYPE_BOOLEAN</code>, - * <code>ClassConstants.INTERNAL_TYPE_BYTE</code>, - * <code>ClassConstants.INTERNAL_TYPE_CHAR</code>, - * <code>ClassConstants.INTERNAL_TYPE_SHORT</code>, - * <code>ClassConstants.INTERNAL_TYPE_INT</code>, - * <code>ClassConstants.INTERNAL_TYPE_LONG</code>, - * <code>ClassConstants.INTERNAL_TYPE_FLOAT</code>, or - * <code>ClassConstants.INTERNAL_TYPE_DOUBLE</code>. + * @return <code>ClassConstants.TYPE_BOOLEAN</code>, + * <code>ClassConstants.TYPE_BYTE</code>, + * <code>ClassConstants.TYPE_CHAR</code>, + * <code>ClassConstants.TYPE_SHORT</code>, + * <code>ClassConstants.TYPE_INT</code>, + * <code>ClassConstants.TYPE_LONG</code>, + * <code>ClassConstants.TYPE_FLOAT</code>, or + * <code>ClassConstants.TYPE_DOUBLE</code>. */ public static char internalTypeFromArrayType(byte arrayType) { switch (arrayType) { - case InstructionConstants.ARRAY_T_BOOLEAN: return ClassConstants.INTERNAL_TYPE_BOOLEAN; - case InstructionConstants.ARRAY_T_CHAR: return ClassConstants.INTERNAL_TYPE_CHAR; - case InstructionConstants.ARRAY_T_FLOAT: return ClassConstants.INTERNAL_TYPE_FLOAT; - case InstructionConstants.ARRAY_T_DOUBLE: return ClassConstants.INTERNAL_TYPE_DOUBLE; - case InstructionConstants.ARRAY_T_BYTE: return ClassConstants.INTERNAL_TYPE_BYTE; - case InstructionConstants.ARRAY_T_SHORT: return ClassConstants.INTERNAL_TYPE_SHORT; - case InstructionConstants.ARRAY_T_INT: return ClassConstants.INTERNAL_TYPE_INT; - case InstructionConstants.ARRAY_T_LONG: return ClassConstants.INTERNAL_TYPE_LONG; + case InstructionConstants.ARRAY_T_BOOLEAN: return ClassConstants.TYPE_BOOLEAN; + case InstructionConstants.ARRAY_T_CHAR: return ClassConstants.TYPE_CHAR; + case InstructionConstants.ARRAY_T_FLOAT: return ClassConstants.TYPE_FLOAT; + case InstructionConstants.ARRAY_T_DOUBLE: return ClassConstants.TYPE_DOUBLE; + case InstructionConstants.ARRAY_T_BYTE: return ClassConstants.TYPE_BYTE; + case InstructionConstants.ARRAY_T_SHORT: return ClassConstants.TYPE_SHORT; + case InstructionConstants.ARRAY_T_INT: return ClassConstants.TYPE_INT; + case InstructionConstants.ARRAY_T_LONG: return ClassConstants.TYPE_LONG; default: throw new IllegalArgumentException("Unknown array type ["+arrayType+"]"); } } diff --git a/src/proguard/classfile/instruction/LookUpSwitchInstruction.java b/src/proguard/classfile/instruction/LookUpSwitchInstruction.java index 807c0cc..fa18f3d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 c9a2957..aecb56c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/instruction/SwitchInstruction.java b/src/proguard/classfile/instruction/SwitchInstruction.java index 3706ba0..c4a0f9a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 45490e5..6abff8f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 6390e0a..1574240 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java b/src/proguard/classfile/instruction/visitor/AllInstructionVisitor.java index 4d739c2..5b606cd 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 index 6b24e98..bdc0ac5 100644 --- a/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java +++ b/src/proguard/classfile/instruction/visitor/InstructionConstantVisitor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,10 +22,8 @@ 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; /** diff --git a/src/proguard/classfile/instruction/visitor/InstructionCounter.java b/src/proguard/classfile/instruction/visitor/InstructionCounter.java index 5623498..6d2609d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 cffb15e..a200f9f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 444fd57..7d2eb0b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 d1eab3e..a9a4e8e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -355,7 +355,7 @@ implements ClassVisitor, 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_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 80a38f7..d6a8c36 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -23,6 +23,8 @@ package proguard.classfile.io; import proguard.classfile.*; import proguard.classfile.attribute.*; import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.target.*; +import proguard.classfile.attribute.annotation.target.visitor.*; import proguard.classfile.attribute.annotation.visitor.*; import proguard.classfile.attribute.preverification.*; import proguard.classfile.attribute.preverification.visitor.*; @@ -52,9 +54,14 @@ implements ClassVisitor, StackMapFrameVisitor, VerificationTypeVisitor, LineNumberInfoVisitor, + ParameterInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, + TypeAnnotationVisitor, + TargetInfoVisitor, + TypePathInfoVisitor, + LocalVariableTargetElementVisitor, ElementValueVisitor { private final RuntimeDataInput dataInput; @@ -375,6 +382,21 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + // Read the parameter information. + methodParametersAttribute.u1parametersCount = dataInput.readUnsignedByte(); + + methodParametersAttribute.parameters = new ParameterInfo[methodParametersAttribute.u1parametersCount]; + for (int index = 0; index < methodParametersAttribute.u1parametersCount; index++) + { + ParameterInfo parameterInfo = new ParameterInfo(); + visitParameterInfo(clazz, method, index, parameterInfo); + methodParametersAttribute.parameters[index] = parameterInfo; + } + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { // Read the exceptions. @@ -518,23 +540,23 @@ implements ClassVisitor, public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) { // Read the parameter annotations. - parameterAnnotationsAttribute.u2parametersCount = dataInput.readUnsignedByte(); + parameterAnnotationsAttribute.u1parametersCount = dataInput.readUnsignedByte(); // The java compilers of JDK 1.5, JDK 1.6, and Eclipse all count the // number of parameters of constructors of non-static inner classes // incorrectly. Fix it right here. int parameterStart = 0; - if (method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + if (method.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT)) { int realParametersCount = ClassUtil.internalMethodParameterCount(method.getDescriptor(clazz)); - parameterStart = realParametersCount - parameterAnnotationsAttribute.u2parametersCount; - parameterAnnotationsAttribute.u2parametersCount = realParametersCount; + parameterStart = realParametersCount - parameterAnnotationsAttribute.u1parametersCount; + parameterAnnotationsAttribute.u1parametersCount = realParametersCount; } - parameterAnnotationsAttribute.u2parameterAnnotationsCount = new int[parameterAnnotationsAttribute.u2parametersCount]; - parameterAnnotationsAttribute.parameterAnnotations = new Annotation[parameterAnnotationsAttribute.u2parametersCount][]; + parameterAnnotationsAttribute.u2parameterAnnotationsCount = new int[parameterAnnotationsAttribute.u1parametersCount]; + parameterAnnotationsAttribute.parameterAnnotations = new Annotation[parameterAnnotationsAttribute.u1parametersCount][]; - for (int parameterIndex = parameterStart; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++) + for (int parameterIndex = parameterStart; parameterIndex < parameterAnnotationsAttribute.u1parametersCount; parameterIndex++) { // Read the parameter annotations of the given parameter. int u2annotationsCount = dataInput.readUnsignedShort(); @@ -554,6 +576,21 @@ implements ClassVisitor, } + public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) + { + // Read the type annotations. + typeAnnotationsAttribute.u2annotationsCount = dataInput.readUnsignedShort(); + + typeAnnotationsAttribute.annotations = new TypeAnnotation[typeAnnotationsAttribute.u2annotationsCount]; + for (int index = 0; index < typeAnnotationsAttribute.u2annotationsCount; index++) + { + TypeAnnotation typeAnnotation = new TypeAnnotation(); + visitTypeAnnotation(clazz, typeAnnotation); + typeAnnotationsAttribute.annotations[index] = typeAnnotation; + } + } + + public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) { // Read the default element value. @@ -702,6 +739,15 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + parameterInfo.u2nameIndex = dataInput.readUnsignedShort(); + parameterInfo.u2accessFlags = dataInput.readUnsignedShort(); + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -748,6 +794,122 @@ implements ClassVisitor, } + // Implementations for TypeAnnotationVisitor. + + public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) + { + // Read the target info. + TargetInfo targetInfo = createTargetInfo(); + targetInfo.accept(clazz, typeAnnotation, this); + typeAnnotation.targetInfo = targetInfo; + + // Read the type path. + int u1pathLength = dataInput.readUnsignedByte(); + + typeAnnotation.typePath = new TypePathInfo[u1pathLength]; + for (int index = 0; index < u1pathLength; index++) + { + TypePathInfo typePathInfo = new TypePathInfo(); + visitTypePathInfo(clazz, typeAnnotation, typePathInfo); + typeAnnotation.typePath[index] = typePathInfo; + } + + // Read the actual annotation. + visitAnnotation(clazz, typeAnnotation); + } + + + // Implementations for TargetInfoVisitor. + + public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo) + { + typeParameterTargetInfo.u1typeParameterIndex = dataInput.readUnsignedByte(); + } + + + public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo) + { + superTypeTargetInfo.u2superTypeIndex = dataInput.readUnsignedShort(); + } + + + public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo) + { + typeParameterBoundTargetInfo.u1typeParameterIndex = dataInput.readUnsignedByte(); + typeParameterBoundTargetInfo.u1boundIndex = dataInput.readUnsignedByte(); + } + + + public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo) + { + } + + + public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo) + { + formalParameterTargetInfo.u1formalParameterIndex = dataInput.readUnsignedByte(); + } + + + public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo) + { + throwsTargetInfo.u2throwsTypeIndex = dataInput.readUnsignedShort(); + } + + + public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) + { + // Read the local variable target elements. + localVariableTargetInfo.u2tableLength = dataInput.readUnsignedShort(); + + localVariableTargetInfo.table = new LocalVariableTargetElement[localVariableTargetInfo.u2tableLength]; + for (int index = 0; index < localVariableTargetInfo.u2tableLength; index++) + { + LocalVariableTargetElement element = new LocalVariableTargetElement(); + visitLocalVariableTargetElement(clazz, method, codeAttribute, typeAnnotation, localVariableTargetInfo, element); + localVariableTargetInfo.table[index] = element; + } + } + + + public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo) + { + catchTargetInfo.u2exceptionTableIndex = dataInput.readUnsignedShort(); + } + + + public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo) + { + offsetTargetInfo.u2offset = dataInput.readUnsignedShort(); + } + + + public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo) + { + typeArgumentTargetInfo.u2offset = dataInput.readUnsignedShort(); + typeArgumentTargetInfo.u1typeArgumentIndex = dataInput.readUnsignedByte(); + } + + + // Implementations for TypePathInfoVisitor. + + public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo) + { + typePathInfo.u1typePathKind = dataInput.readUnsignedByte(); + typePathInfo.u1typeArgumentIndex = dataInput.readUnsignedByte(); + } + + + // Implementations for LocalVariableTargetElementVisitor. + + public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement) + { + localVariableTargetElement.u2startPC = dataInput.readShort(); + localVariableTargetElement.u2length = dataInput.readShort(); + localVariableTargetElement.u2index = dataInput.readShort(); + } + + // Implementations for ElementValueVisitor. public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) @@ -813,7 +975,7 @@ implements ClassVisitor, 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_MethodType: return new MethodTypeConstant(); case ClassConstants.CONSTANT_NameAndType: return new NameAndTypeConstant(); default: throw new RuntimeException("Unknown constant type ["+u1tag+"] in constant pool"); @@ -837,6 +999,7 @@ implements ClassVisitor, attributeName.equals(ClassConstants.ATTR_Synthetic) ? (Attribute)new SyntheticAttribute(): attributeName.equals(ClassConstants.ATTR_Signature) ? (Attribute)new SignatureAttribute(): attributeName.equals(ClassConstants.ATTR_ConstantValue) ? (Attribute)new ConstantValueAttribute(): + attributeName.equals(ClassConstants.ATTR_MethodParameters) ? (Attribute)new MethodParametersAttribute(): attributeName.equals(ClassConstants.ATTR_Exceptions) ? (Attribute)new ExceptionsAttribute(): attributeName.equals(ClassConstants.ATTR_Code) ? (Attribute)new CodeAttribute(): attributeName.equals(ClassConstants.ATTR_StackMap) ? (Attribute)new StackMapAttribute(): @@ -848,8 +1011,10 @@ implements ClassVisitor, attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleAnnotations) ? (Attribute)new RuntimeInvisibleAnnotationsAttribute(): attributeName.equals(ClassConstants.ATTR_RuntimeVisibleParameterAnnotations) ? (Attribute)new RuntimeVisibleParameterAnnotationsAttribute(): attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleParameterAnnotations) ? (Attribute)new RuntimeInvisibleParameterAnnotationsAttribute(): + attributeName.equals(ClassConstants.ATTR_RuntimeVisibleTypeAnnotations) ? (Attribute)new RuntimeVisibleTypeAnnotationsAttribute(): + attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleTypeAnnotations) ? (Attribute)new RuntimeInvisibleTypeAnnotationsAttribute(): attributeName.equals(ClassConstants.ATTR_AnnotationDefault) ? (Attribute)new AnnotationDefaultAttribute(): - (Attribute)new UnknownAttribute(u4attributeLength); + (Attribute)new UnknownAttribute(u2attributeNameIndex, u4attributeLength); attribute.u2attributeNameIndex = u2attributeNameIndex; return attribute; @@ -892,20 +1057,54 @@ implements ClassVisitor, } + private TargetInfo createTargetInfo() + { + byte u1targetType = dataInput.readByte(); + + switch (u1targetType) + { + case ClassConstants.ANNOTATION_TARGET_ParameterGenericClass: + case ClassConstants.ANNOTATION_TARGET_ParameterGenericMethod: return new TypeParameterTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Extends: return new SuperTypeTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_BoundGenericClass: + case ClassConstants.ANNOTATION_TARGET_BoundGenericMethod: return new TypeParameterBoundTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Field: + case ClassConstants.ANNOTATION_TARGET_Return: + case ClassConstants.ANNOTATION_TARGET_Receiver: return new EmptyTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Parameter: return new FormalParameterTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Throws: return new ThrowsTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_LocalVariable: + case ClassConstants.ANNOTATION_TARGET_ResourceVariable: return new LocalVariableTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Catch: return new CatchTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_InstanceOf: + case ClassConstants.ANNOTATION_TARGET_New: + case ClassConstants.ANNOTATION_TARGET_MethodReferenceNew: + case ClassConstants.ANNOTATION_TARGET_MethodReference: return new OffsetTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Cast: + case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethodNew: + case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethod: + case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethodReferenceNew: + case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethodReference: return new TypeArgumentTargetInfo(u1targetType); + + default: throw new RuntimeException("Unknown annotation target type ["+u1targetType+"]"); + } + } + + private ElementValue createElementValue() { int u1tag = dataInput.readUnsignedByte(); switch (u1tag) { - case ClassConstants.INTERNAL_TYPE_BOOLEAN: - case ClassConstants.INTERNAL_TYPE_BYTE: - case ClassConstants.INTERNAL_TYPE_CHAR: - case ClassConstants.INTERNAL_TYPE_SHORT: - case ClassConstants.INTERNAL_TYPE_INT: - case ClassConstants.INTERNAL_TYPE_FLOAT: - case ClassConstants.INTERNAL_TYPE_LONG: - case ClassConstants.INTERNAL_TYPE_DOUBLE: + case ClassConstants.TYPE_BOOLEAN: + case ClassConstants.TYPE_BYTE: + case ClassConstants.TYPE_CHAR: + case ClassConstants.TYPE_SHORT: + case ClassConstants.TYPE_INT: + case ClassConstants.TYPE_FLOAT: + case ClassConstants.TYPE_LONG: + case ClassConstants.TYPE_DOUBLE: case ClassConstants.ELEMENT_VALUE_STRING_CONSTANT: return new ConstantElementValue((char)u1tag); case ClassConstants.ELEMENT_VALUE_ENUM_CONSTANT: return new EnumConstantElementValue(); diff --git a/src/proguard/classfile/io/ProgramClassWriter.java b/src/proguard/classfile/io/ProgramClassWriter.java index dbf1de3..bcc3403 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -23,6 +23,8 @@ package proguard.classfile.io; import proguard.classfile.*; import proguard.classfile.attribute.*; import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.target.*; +import proguard.classfile.attribute.annotation.target.visitor.*; import proguard.classfile.attribute.annotation.visitor.*; import proguard.classfile.attribute.preverification.*; import proguard.classfile.attribute.preverification.visitor.*; @@ -289,9 +291,14 @@ implements ClassVisitor, StackMapFrameVisitor, VerificationTypeVisitor, LineNumberInfoVisitor, + ParameterInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, + TypeAnnotationVisitor, + TargetInfoVisitor, + TypePathInfoVisitor, + LocalVariableTargetElementVisitor, ElementValueVisitor { // Implementations for AttributeVisitor. @@ -364,6 +371,15 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + // Write the parameter information. + dataOutput.writeByte(methodParametersAttribute.u1parametersCount); + + methodParametersAttribute.parametersAccept(clazz, method, this); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { // Write the exceptions. @@ -456,9 +472,9 @@ implements ClassVisitor, public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) { // Write the parameter annotations. - dataOutput.writeByte(parameterAnnotationsAttribute.u2parametersCount); + dataOutput.writeByte(parameterAnnotationsAttribute.u1parametersCount); - for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++) + for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u1parametersCount; parameterIndex++) { // Write the parameter annotations of the given parameter. int u2annotationsCount = parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]; @@ -475,6 +491,15 @@ implements ClassVisitor, } + public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) + { + // Write the type annotations. + dataOutput.writeShort(typeAnnotationsAttribute.u2annotationsCount); + + typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this); + } + + public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) { // Write the default element value. @@ -541,6 +566,15 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + dataOutput.writeShort(parameterInfo.u2nameIndex); + dataOutput.writeShort(parameterInfo.u2accessFlags); + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -579,6 +613,110 @@ implements ClassVisitor, } + // Implementations for TypeAnnotationVisitor. + + public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) + { + // Write the target info. + dataOutput.writeByte(typeAnnotation.targetInfo.u1targetType); + + typeAnnotation.targetInfoAccept(clazz, this); + + // Write the type path. + dataOutput.writeByte(typeAnnotation.typePath.length); + + typeAnnotation.typePathInfosAccept(clazz, this); + + // Write the actual annotation. + visitAnnotation(clazz, typeAnnotation); + } + + + // Implementations for TargetInfoVisitor. + + public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo) + { + dataOutput.writeByte(typeParameterTargetInfo.u1typeParameterIndex); + } + + + public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo) + { + dataOutput.writeShort(superTypeTargetInfo.u2superTypeIndex); + } + + + public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo) + { + dataOutput.writeByte(typeParameterBoundTargetInfo.u1typeParameterIndex); + dataOutput.writeByte(typeParameterBoundTargetInfo.u1boundIndex); + } + + + public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo) + { + } + + + public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo) + { + dataOutput.writeByte(formalParameterTargetInfo.u1formalParameterIndex); + } + + + public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo) + { + dataOutput.writeShort(throwsTargetInfo.u2throwsTypeIndex); + } + + + public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) + { + // Write the local variable target elements. + dataOutput.writeShort(localVariableTargetInfo.u2tableLength); + + localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this); + } + + + public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo) + { + dataOutput.writeShort(catchTargetInfo.u2exceptionTableIndex); + } + + + public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo) + { + dataOutput.writeShort(offsetTargetInfo.u2offset); + } + + + public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo) + { + dataOutput.writeShort(typeArgumentTargetInfo.u2offset); + dataOutput.writeByte(typeArgumentTargetInfo.u1typeArgumentIndex); + } + + + // Implementations for TypePathInfoVisitor. + + public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo) + { + dataOutput.writeByte(typePathInfo.u1typePathKind); + dataOutput.writeByte(typePathInfo.u1typeArgumentIndex); + } + + + // Implementations for LocalVariableTargetElementVisitor. + + public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement) + { + dataOutput.writeShort(localVariableTargetElement.u2startPC); + dataOutput.writeShort(localVariableTargetElement.u2length); + dataOutput.writeShort(localVariableTargetElement.u2index); + } + + // Implementations for ElementValueVisitor. public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) diff --git a/src/proguard/classfile/io/RuntimeDataInput.java b/src/proguard/classfile/io/RuntimeDataInput.java index ce2d1a5..905d828 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 44acc70..9d89332 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 d16f576..97fda89 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +40,9 @@ public class AccessUtil // The mask of access flags. private static final int ACCESS_MASK = - ClassConstants.INTERNAL_ACC_PUBLIC | - ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_PROTECTED; + ClassConstants.ACC_PUBLIC | + ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_PROTECTED; /** @@ -56,10 +56,10 @@ public class AccessUtil { switch (accessFlags & ACCESS_MASK) { - case ClassConstants.INTERNAL_ACC_PRIVATE: return PRIVATE; - default: return PACKAGE_VISIBLE; - case ClassConstants.INTERNAL_ACC_PROTECTED: return PROTECTED; - case ClassConstants.INTERNAL_ACC_PUBLIC: return PUBLIC; + case ClassConstants.ACC_PRIVATE: return PRIVATE; + default: return PACKAGE_VISIBLE; + case ClassConstants.ACC_PROTECTED: return PROTECTED; + case ClassConstants.ACC_PUBLIC: return PUBLIC; } } @@ -78,10 +78,10 @@ public class AccessUtil { switch (accessLevel) { - case PRIVATE: return ClassConstants.INTERNAL_ACC_PRIVATE; + case PRIVATE: return ClassConstants.ACC_PRIVATE; default: return 0; - case PROTECTED: return ClassConstants.INTERNAL_ACC_PROTECTED; - case PUBLIC: return ClassConstants.INTERNAL_ACC_PUBLIC; + case PROTECTED: return ClassConstants.ACC_PROTECTED; + case PUBLIC: return ClassConstants.ACC_PUBLIC; } } @@ -94,9 +94,9 @@ public class AccessUtil public static int replaceAccessFlags(int accessFlags, int newAccessFlags) { // A private class member should not be explicitly final. - if (newAccessFlags == ClassConstants.INTERNAL_ACC_PRIVATE) + if (newAccessFlags == ClassConstants.ACC_PRIVATE) { - accessFlags &= ~ClassConstants.INTERNAL_ACC_FINAL; + accessFlags &= ~ClassConstants.ACC_FINAL; } return (accessFlags & ~ACCESS_MASK) | diff --git a/src/proguard/classfile/util/AllParameterVisitor.java b/src/proguard/classfile/util/AllParameterVisitor.java new file mode 100644 index 0000000..3695dbb --- /dev/null +++ b/src/proguard/classfile/util/AllParameterVisitor.java @@ -0,0 +1,239 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.visitor.*; + +/** + * This MemberVisitor lets a given parameter visitor visit all the parameters + * of the methods that it visits. The parameters do not include or count the + * 'this' parameter or the return value. + * + * @author Eric Lafortune + */ +public class AllParameterVisitor +implements MemberVisitor +{ + private final ParameterVisitor parameterVisitor; + + + /** + * Creates a new AllParameterVisitor for the given parameter + * visitor. + */ + public AllParameterVisitor(ParameterVisitor parameterVisitor) + { + this.parameterVisitor = parameterVisitor; + } + + + // Implementations for MemberVisitor. + + public void visitProgramField(ProgramClass programClass, ProgramField programField) + { + visitFieldType(programClass, + programField, + programField.referencedClass); + } + + + public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) + { + visitFieldType(libraryClass, + libraryField, + libraryField.referencedClass); + } + + + public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) + { + visitParameters(programClass, + programMethod, + programMethod.referencedClasses); + } + + + public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) + { + visitParameters(libraryClass, + libraryMethod, + libraryMethod.referencedClasses); + } + + + // Small utility methods. + + /** + * Lets the parameter visitor visit the type of the given field. + */ + private void visitFieldType(Clazz clazz, + Field field, + Clazz referencedClass) + { + String descriptor = field.getDescriptor(clazz); + parameterVisitor.visitParameter(clazz, + field, + 0, + 1, + 0, + ClassUtil.internalTypeSize(descriptor), + descriptor, + referencedClass); + } + + + /** + * Lets the parameter visitor visit the parameters of the given method. + */ + private void visitParameters(Clazz clazz, + Method method, + Clazz[] referencedClasses) + { + String descriptor = method.getDescriptor(clazz); + + // Count the number of parameters and their total size. + int parameterCount = 0; + int parameterSize = 0; + + int index = 1; + + loop: while (true) + { + char c = descriptor.charAt(index++); + switch (c) + { + case ClassConstants.TYPE_LONG: + case ClassConstants.TYPE_DOUBLE: + { + // Long and double primitive types. + parameterSize++; + break; + } + default: + { + // All other primitive types. + break; + } + case ClassConstants.TYPE_CLASS_START: + { + // Class types. + // Skip the class name. + index = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1; + break; + } + case ClassConstants.TYPE_ARRAY: + { + // Array types. + // Skip all array characters. + while ((c = descriptor.charAt(index++)) == ClassConstants.TYPE_ARRAY) {} + + if (c == ClassConstants.TYPE_CLASS_START) + { + // Skip the class type. + index = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1; + } + break; + } + case ClassConstants.METHOD_ARGUMENTS_CLOSE: + { + break loop; + } + } + + parameterCount++; + parameterSize++; + } + + // Visit the parameters. + int parameterIndex = 0; + int parameterOffset = 0; + int referenceClassIndex = 0; + + index = 1; + + while (true) + { + int newIndex = index + 1; + int thisParameterSize = 1; + Clazz referencedClass = null; + + char c = descriptor.charAt(index); + switch (c) + { + case ClassConstants.TYPE_LONG: + case ClassConstants.TYPE_DOUBLE: + { + // Long and double primitive types. + thisParameterSize = 2; + break; + } + default: + { + // All other primitive types. + break; + } + case ClassConstants.TYPE_CLASS_START: + { + // Class types. + // Skip the class name. + newIndex = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, newIndex) + 1; + referencedClass = referencedClasses == null ? null : + referencedClasses[referenceClassIndex++]; + break; + } + case ClassConstants.TYPE_ARRAY: + { + // Array types. + // Skip all array characters. + while ((c = descriptor.charAt(newIndex++)) == ClassConstants.TYPE_ARRAY) {} + + if (c == ClassConstants.TYPE_CLASS_START) + { + // Skip the class type. + newIndex = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, newIndex) + 1; + referencedClass = referencedClasses == null ? null : + referencedClasses[referenceClassIndex++]; + } + break; + } + case ClassConstants.METHOD_ARGUMENTS_CLOSE: + { + // End of the method parameters. + return; + } + } + + parameterVisitor.visitParameter(clazz, + method, + parameterIndex++, + parameterCount, + parameterOffset, + parameterSize, + descriptor.substring(index, newIndex), + referencedClass); + + // Continue with the next parameter. + index = newIndex; + parameterOffset += thisParameterSize; + } + } +} diff --git a/src/proguard/classfile/util/ClassReferenceInitializer.java b/src/proguard/classfile/util/ClassReferenceInitializer.java index a5748ee..3baf422 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -165,7 +165,15 @@ implements ClassVisitor, { // Fill out the String class. stringConstant.javaLangStringClass = - findClass(clazz.getName(), ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING); + findClass(clazz.getName(), ClassConstants.NAME_JAVA_LANG_STRING); + } + + + public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + { + invokeDynamicConstant.referencedClasses = + findReferencedClasses(clazz.getName(), + invokeDynamicConstant.getType(clazz)); } @@ -173,7 +181,7 @@ implements ClassVisitor, { // Fill out the MethodHandle class. methodHandleConstant.javaLangInvokeMethodHandleClass = - findClass(clazz.getName(), ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_HANDLE); + findClass(clazz.getName(), ClassConstants.NAME_JAVA_LANG_INVOKE_METHOD_HANDLE); } @@ -184,7 +192,7 @@ implements ClassVisitor, // Methods for array types should be found in the Object class. if (ClassUtil.isInternalArrayType(className)) { - className = ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT; + className = ClassConstants.NAME_JAVA_LANG_OBJECT; } // See if we can find the referenced class. @@ -246,7 +254,7 @@ implements ClassVisitor, // Fill out the Class class. classConstant.javaLangClassClass = - findClass(className, ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS); + findClass(className, ClassConstants.NAME_JAVA_LANG_CLASS); } @@ -254,7 +262,11 @@ implements ClassVisitor, { // Fill out the MethodType class. methodTypeConstant.javaLangInvokeMethodTypeClass = - findClass(clazz.getName(), ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_TYPE); + findClass(clazz.getName(), ClassConstants.NAME_JAVA_LANG_INVOKE_METHOD_TYPE); + + methodTypeConstant.referencedClasses = + findReferencedClasses(clazz.getName(), + methodTypeConstant.getType(clazz)); } @@ -327,7 +339,7 @@ implements ClassVisitor, { signatureAttribute.referencedClasses = findReferencedClasses(clazz.getName(), - clazz.getString(signatureAttribute.u2signatureIndex)); + signatureAttribute.getSignature(clazz)); } @@ -358,7 +370,7 @@ implements ClassVisitor, { localVariableInfo.referencedClass = findReferencedClass(clazz.getName(), - clazz.getString(localVariableInfo.u2descriptorIndex)); + localVariableInfo.getDescriptor(clazz)); } @@ -368,7 +380,7 @@ implements ClassVisitor, { localVariableTypeInfo.referencedClasses = findReferencedClasses(clazz.getName(), - clazz.getString(localVariableTypeInfo.u2signatureIndex)); + localVariableTypeInfo.getSignature(clazz)); } @@ -378,7 +390,7 @@ implements ClassVisitor, { annotation.referencedClasses = findReferencedClasses(clazz.getName(), - clazz.getString(annotation.u2typeIndex)); + annotation.getType(clazz)); // Initialize the element values. annotation.elementValuesAccept(clazz, this); @@ -399,7 +411,7 @@ implements ClassVisitor, enumConstantElementValue.referencedClasses = findReferencedClasses(clazz.getName(), - clazz.getString(enumConstantElementValue.u2typeNameIndex)); + enumConstantElementValue.getTypeName(clazz)); } @@ -409,7 +421,7 @@ implements ClassVisitor, classElementValue.referencedClasses = findReferencedClasses(clazz.getName(), - clazz.getString(classElementValue.u2classInfoIndex)); + classElementValue.getClassName(clazz)); } @@ -443,7 +455,7 @@ implements ClassVisitor, { // See if we can find the method in the referenced class // (ignoring the descriptor). - String name = clazz.getString(elementValue.u2elementNameIndex); + String name = elementValue.getMethodName(clazz); Clazz referencedClass = annotation.referencedClasses[0]; elementValue.referencedClass = referencedClass; diff --git a/src/proguard/classfile/util/ClassSubHierarchyInitializer.java b/src/proguard/classfile/util/ClassSubHierarchyInitializer.java index 993a559..8a0e45e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 fb431b8..1e765cb 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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/ClassUtil.java b/src/proguard/classfile/util/ClassUtil.java index fb38616..037d31a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.util; -import proguard.classfile.ClassConstants; +import proguard.classfile.*; import java.util.List; @@ -91,18 +91,20 @@ public class ClassUtil public static int internalClassVersion(String classVersion) { return - classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_0) || - classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_1) ? ClassConstants.INTERNAL_CLASS_VERSION_1_0 : - classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_2) ? ClassConstants.INTERNAL_CLASS_VERSION_1_2 : - classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_3) ? ClassConstants.INTERNAL_CLASS_VERSION_1_3 : - classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_4) ? ClassConstants.INTERNAL_CLASS_VERSION_1_4 : - classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_5_ALIAS) || - 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; + classVersion.equals(JavaConstants.CLASS_VERSION_1_0) || + classVersion.equals(JavaConstants.CLASS_VERSION_1_1) ? ClassConstants.CLASS_VERSION_1_0 : + classVersion.equals(JavaConstants.CLASS_VERSION_1_2) ? ClassConstants.CLASS_VERSION_1_2 : + classVersion.equals(JavaConstants.CLASS_VERSION_1_3) ? ClassConstants.CLASS_VERSION_1_3 : + classVersion.equals(JavaConstants.CLASS_VERSION_1_4) ? ClassConstants.CLASS_VERSION_1_4 : + classVersion.equals(JavaConstants.CLASS_VERSION_1_5_ALIAS) || + classVersion.equals(JavaConstants.CLASS_VERSION_1_5) ? ClassConstants.CLASS_VERSION_1_5 : + classVersion.equals(JavaConstants.CLASS_VERSION_1_6_ALIAS) || + classVersion.equals(JavaConstants.CLASS_VERSION_1_6) ? ClassConstants.CLASS_VERSION_1_6 : + classVersion.equals(JavaConstants.CLASS_VERSION_1_7_ALIAS) || + classVersion.equals(JavaConstants.CLASS_VERSION_1_7) ? ClassConstants.CLASS_VERSION_1_7 : + classVersion.equals(JavaConstants.CLASS_VERSION_1_8_ALIAS) || + classVersion.equals(JavaConstants.CLASS_VERSION_1_8) ? ClassConstants.CLASS_VERSION_1_8 : + 0; } @@ -115,14 +117,15 @@ public class ClassUtil { switch (classVersion) { - case ClassConstants.INTERNAL_CLASS_VERSION_1_0: return ClassConstants.EXTERNAL_CLASS_VERSION_1_0; - case ClassConstants.INTERNAL_CLASS_VERSION_1_2: return ClassConstants.EXTERNAL_CLASS_VERSION_1_2; - case ClassConstants.INTERNAL_CLASS_VERSION_1_3: return ClassConstants.EXTERNAL_CLASS_VERSION_1_3; - 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; + case ClassConstants.CLASS_VERSION_1_0: return JavaConstants.CLASS_VERSION_1_0; + case ClassConstants.CLASS_VERSION_1_2: return JavaConstants.CLASS_VERSION_1_2; + case ClassConstants.CLASS_VERSION_1_3: return JavaConstants.CLASS_VERSION_1_3; + case ClassConstants.CLASS_VERSION_1_4: return JavaConstants.CLASS_VERSION_1_4; + case ClassConstants.CLASS_VERSION_1_5: return JavaConstants.CLASS_VERSION_1_5; + case ClassConstants.CLASS_VERSION_1_6: return JavaConstants.CLASS_VERSION_1_6; + case ClassConstants.CLASS_VERSION_1_7: return JavaConstants.CLASS_VERSION_1_7; + case ClassConstants.CLASS_VERSION_1_8: return JavaConstants.CLASS_VERSION_1_8; + default: return null; } } @@ -134,15 +137,15 @@ 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_7) + if (classVersion < ClassConstants.CLASS_VERSION_1_0 || + classVersion > ClassConstants.CLASS_VERSION_1_8) { throw new UnsupportedOperationException("Unsupported class version number ["+ internalMajorClassVersion(classVersion)+"."+ internalMinorClassVersion(classVersion)+"] (maximum "+ - ClassConstants.INTERNAL_CLASS_VERSION_1_7_MAJOR+"."+ - ClassConstants.INTERNAL_CLASS_VERSION_1_7_MINOR+", Java "+ - ClassConstants.EXTERNAL_CLASS_VERSION_1_7+")"); + ClassConstants.CLASS_VERSION_1_8_MAJOR+"."+ + ClassConstants.CLASS_VERSION_1_8_MINOR+", Java "+ + JavaConstants.CLASS_VERSION_1_8+")"); } } @@ -156,8 +159,8 @@ public class ClassUtil */ public static String internalClassName(String externalClassName) { - return externalClassName.replace(ClassConstants.EXTERNAL_PACKAGE_SEPARATOR, - ClassConstants.INTERNAL_PACKAGE_SEPARATOR); + return externalClassName.replace(JavaConstants.PACKAGE_SEPARATOR, + ClassConstants.PACKAGE_SEPARATOR); } @@ -186,11 +189,11 @@ public class ClassUtil */ public static String externalClassName(String internalClassName) { - return //internalClassName.startsWith(ClassConstants.INTERNAL_PACKAGE_JAVA_LANG) && - //internalClassName.indexOf(ClassConstants.INTERNAL_PACKAGE_SEPARATOR, ClassConstants.INTERNAL_PACKAGE_JAVA_LANG.length() + 1) < 0 ? - //internalClassName.substring(ClassConstants.INTERNAL_PACKAGE_JAVA_LANG.length()) : - internalClassName.replace(ClassConstants.INTERNAL_PACKAGE_SEPARATOR, - ClassConstants.EXTERNAL_PACKAGE_SEPARATOR); + return //internalClassName.startsWith(ClassConstants.PACKAGE_JAVA_LANG) && + //internalClassName.indexOf(ClassConstants.PACKAGE_SEPARATOR, ClassConstants.PACKAGE_JAVA_LANG.length() + 1) < 0 ? + //internalClassName.substring(ClassConstants.PACKAGE_JAVA_LANG.length()) : + internalClassName.replace(ClassConstants.PACKAGE_SEPARATOR, + JavaConstants.PACKAGE_SEPARATOR); } @@ -204,7 +207,7 @@ public class ClassUtil */ public static String externalBaseType(String externalArrayType) { - int index = externalArrayType.indexOf(ClassConstants.EXTERNAL_TYPE_ARRAY); + int index = externalArrayType.indexOf(JavaConstants.TYPE_ARRAY); return index >= 0 ? externalArrayType.substring(0, index) : externalArrayType; @@ -221,7 +224,7 @@ public class ClassUtil */ public static String externalShortClassName(String externalClassName) { - int index = externalClassName.lastIndexOf(ClassConstants.EXTERNAL_PACKAGE_SEPARATOR); + int index = externalClassName.lastIndexOf(JavaConstants.PACKAGE_SEPARATOR); return externalClassName.substring(index+1); } @@ -236,7 +239,7 @@ public class ClassUtil public static boolean isInternalArrayType(String internalType) { return internalType.length() > 1 && - internalType.charAt(0) == ClassConstants.INTERNAL_TYPE_ARRAY; + internalType.charAt(0) == ClassConstants.TYPE_ARRAY; } @@ -249,7 +252,7 @@ public class ClassUtil public static int internalArrayTypeDimensionCount(String internalType) { int dimensions = 0; - while (internalType.charAt(dimensions) == ClassConstants.INTERNAL_TYPE_ARRAY) + while (internalType.charAt(dimensions) == ClassConstants.TYPE_ARRAY) { dimensions++; } @@ -270,9 +273,9 @@ public class ClassUtil */ public static boolean isInternalArrayInterfaceName(String internalClassName) { - return ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT.equals(internalClassName) || - ClassConstants.INTERNAL_NAME_JAVA_LANG_CLONEABLE.equals(internalClassName) || - ClassConstants.INTERNAL_NAME_JAVA_IO_SERIALIZABLE.equals(internalClassName); + return ClassConstants.NAME_JAVA_LANG_OBJECT.equals(internalClassName) || + ClassConstants.NAME_JAVA_LANG_CLONEABLE.equals(internalClassName) || + ClassConstants.NAME_JAVA_IO_SERIALIZABLE.equals(internalClassName); } @@ -286,14 +289,14 @@ public class ClassUtil */ public static boolean isInternalPrimitiveType(char internalType) { - return internalType == ClassConstants.INTERNAL_TYPE_BOOLEAN || - internalType == ClassConstants.INTERNAL_TYPE_BYTE || - internalType == ClassConstants.INTERNAL_TYPE_CHAR || - internalType == ClassConstants.INTERNAL_TYPE_SHORT || - internalType == ClassConstants.INTERNAL_TYPE_INT || - internalType == ClassConstants.INTERNAL_TYPE_FLOAT || - internalType == ClassConstants.INTERNAL_TYPE_LONG || - internalType == ClassConstants.INTERNAL_TYPE_DOUBLE; + return internalType == ClassConstants.TYPE_BOOLEAN || + internalType == ClassConstants.TYPE_BYTE || + internalType == ClassConstants.TYPE_CHAR || + internalType == ClassConstants.TYPE_SHORT || + internalType == ClassConstants.TYPE_INT || + internalType == ClassConstants.TYPE_FLOAT || + internalType == ClassConstants.TYPE_LONG || + internalType == ClassConstants.TYPE_DOUBLE; } @@ -307,8 +310,8 @@ public class ClassUtil public static boolean isInternalCategory2Type(String internalType) { return internalType.length() == 1 && - (internalType.charAt(0) == ClassConstants.INTERNAL_TYPE_LONG || - internalType.charAt(0) == ClassConstants.INTERNAL_TYPE_DOUBLE); + (internalType.charAt(0) == ClassConstants.TYPE_LONG || + internalType.charAt(0) == ClassConstants.TYPE_DOUBLE); } @@ -324,8 +327,8 @@ public class ClassUtil { int length = internalType.length(); return length > 1 && -// internalType.charAt(0) == ClassConstants.INTERNAL_TYPE_CLASS_START && - internalType.charAt(length-1) == ClassConstants.INTERNAL_TYPE_CLASS_END; +// internalType.charAt(0) == ClassConstants.TYPE_CLASS_START && + internalType.charAt(length-1) == ClassConstants.TYPE_CLASS_END; } @@ -359,12 +362,12 @@ public class ClassUtil for (int dimension = 0; dimension < dimensionCount; dimension++) { - buffer.append(ClassConstants.INTERNAL_TYPE_ARRAY); + buffer.append(ClassConstants.TYPE_ARRAY); } - return buffer.append(ClassConstants.INTERNAL_TYPE_CLASS_START) + return buffer.append(ClassConstants.TYPE_CLASS_START) .append(internalClassName) - .append(ClassConstants.INTERNAL_TYPE_CLASS_END) + .append(ClassConstants.TYPE_CLASS_END) .toString(); } @@ -380,7 +383,7 @@ public class ClassUtil */ public static String internalTypeFromArrayType(String internalArrayType) { - int index = internalArrayType.lastIndexOf(ClassConstants.INTERNAL_TYPE_ARRAY); + int index = internalArrayType.lastIndexOf(ClassConstants.TYPE_ARRAY); return internalArrayType.substring(index+1); } @@ -399,7 +402,7 @@ public class ClassUtil public static String internalClassNameFromClassType(String internalClassType) { return isInternalClassType(internalClassType) ? - internalClassType.substring(internalClassType.indexOf(ClassConstants.INTERNAL_TYPE_CLASS_START)+1, + internalClassType.substring(internalClassType.indexOf(ClassConstants.TYPE_CLASS_START)+1, internalClassType.length()-1) : internalClassType; } @@ -442,8 +445,8 @@ public class ClassUtil */ public static boolean isInitializer(String internalMethodName) { - return internalMethodName.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) || - internalMethodName.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT); + return internalMethodName.equals(ClassConstants.METHOD_NAME_CLINIT) || + internalMethodName.equals(ClassConstants.METHOD_NAME_INIT); } @@ -456,7 +459,7 @@ public class ClassUtil */ public static String internalMethodReturnType(String internalMethodDescriptor) { - int index = internalMethodDescriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE); + int index = internalMethodDescriptor.indexOf(ClassConstants.METHOD_ARGUMENTS_CLOSE); return internalMethodDescriptor.substring(index + 1); } @@ -470,18 +473,38 @@ public class ClassUtil */ public static int internalMethodParameterCount(String internalMethodDescriptor) { - InternalTypeEnumeration internalTypeEnumeration = - new InternalTypeEnumeration(internalMethodDescriptor); - int counter = 0; - while (internalTypeEnumeration.hasMoreTypes()) - { - internalTypeEnumeration.nextType(); + int index = 1; - counter++; + while (true) + { + char c = internalMethodDescriptor.charAt(index++); + switch (c) + { + case ClassConstants.TYPE_ARRAY: + { + // Just ignore all array characters. + break; + } + case ClassConstants.TYPE_CLASS_START: + { + counter++; + + // Skip the class name. + index = internalMethodDescriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1; + break; + } + default: + { + counter++; + break; + } + case ClassConstants.METHOD_ARGUMENTS_CLOSE: + { + return counter; + } + } } - - return counter; } @@ -516,7 +539,7 @@ public class ClassUtil int accessFlags) { return internalMethodParameterSize(internalMethodDescriptor, - (accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0); + (accessFlags & ClassConstants.ACC_STATIC) != 0); } @@ -535,18 +558,53 @@ public class ClassUtil public static int internalMethodParameterSize(String internalMethodDescriptor, boolean isStatic) { - InternalTypeEnumeration internalTypeEnumeration = - new InternalTypeEnumeration(internalMethodDescriptor); + int size = isStatic ? 0 : 1; + int index = 1; - int size = isStatic ? 0 : 1; - while (internalTypeEnumeration.hasMoreTypes()) + while (true) { - String internalType = internalTypeEnumeration.nextType(); - - size += internalTypeSize(internalType); + char c = internalMethodDescriptor.charAt(index++); + switch (c) + { + case ClassConstants.TYPE_LONG: + case ClassConstants.TYPE_DOUBLE: + { + size += 2; + break; + } + case ClassConstants.TYPE_CLASS_START: + { + size++; + + // Skip the class name. + index = internalMethodDescriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1; + break; + } + case ClassConstants.TYPE_ARRAY: + { + size++; + + // Skip all array characters. + while ((c = internalMethodDescriptor.charAt(index++)) == ClassConstants.TYPE_ARRAY) {} + + if (c == ClassConstants.TYPE_CLASS_START) + { + // Skip the class type. + index = internalMethodDescriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1; + } + break; + } + default: + { + size++; + break; + } + case ClassConstants.METHOD_ARGUMENTS_CLOSE: + { + return size; + } + } } - - return size; } @@ -564,12 +622,12 @@ public class ClassUtil if (internalType.length() == 1) { char internalPrimitiveType = internalType.charAt(0); - if (internalPrimitiveType == ClassConstants.INTERNAL_TYPE_LONG || - internalPrimitiveType == ClassConstants.INTERNAL_TYPE_DOUBLE) + if (internalPrimitiveType == ClassConstants.TYPE_LONG || + internalPrimitiveType == ClassConstants.TYPE_DOUBLE) { return 2; } - else if (internalPrimitiveType == ClassConstants.INTERNAL_TYPE_VOID) + else if (internalPrimitiveType == ClassConstants.TYPE_VOID) { return 0; } @@ -594,43 +652,33 @@ public class ClassUtil int dimensionCount = externalArrayTypeDimensionCount(externalType); if (dimensionCount > 0) { - externalType = externalType.substring(0, externalType.length() - dimensionCount * ClassConstants.EXTERNAL_TYPE_ARRAY.length()); + externalType = externalType.substring(0, externalType.length() - dimensionCount * JavaConstants.TYPE_ARRAY.length()); } // Analyze the actual type part. char internalTypeChar = - externalType.equals(ClassConstants.EXTERNAL_TYPE_VOID ) ? - ClassConstants.INTERNAL_TYPE_VOID : - externalType.equals(ClassConstants.EXTERNAL_TYPE_BOOLEAN) ? - ClassConstants.INTERNAL_TYPE_BOOLEAN : - externalType.equals(ClassConstants.EXTERNAL_TYPE_BYTE ) ? - ClassConstants.INTERNAL_TYPE_BYTE : - externalType.equals(ClassConstants.EXTERNAL_TYPE_CHAR ) ? - ClassConstants.INTERNAL_TYPE_CHAR : - externalType.equals(ClassConstants.EXTERNAL_TYPE_SHORT ) ? - ClassConstants.INTERNAL_TYPE_SHORT : - externalType.equals(ClassConstants.EXTERNAL_TYPE_INT ) ? - ClassConstants.INTERNAL_TYPE_INT : - externalType.equals(ClassConstants.EXTERNAL_TYPE_FLOAT ) ? - ClassConstants.INTERNAL_TYPE_FLOAT : - externalType.equals(ClassConstants.EXTERNAL_TYPE_LONG ) ? - ClassConstants.INTERNAL_TYPE_LONG : - externalType.equals(ClassConstants.EXTERNAL_TYPE_DOUBLE ) ? - ClassConstants.INTERNAL_TYPE_DOUBLE : - externalType.equals("%" ) ? - '%' : - (char)0; + externalType.equals(JavaConstants.TYPE_VOID ) ? ClassConstants.TYPE_VOID : + externalType.equals(JavaConstants.TYPE_BOOLEAN) ? ClassConstants.TYPE_BOOLEAN : + externalType.equals(JavaConstants.TYPE_BYTE ) ? ClassConstants.TYPE_BYTE : + externalType.equals(JavaConstants.TYPE_CHAR ) ? ClassConstants.TYPE_CHAR : + externalType.equals(JavaConstants.TYPE_SHORT ) ? ClassConstants.TYPE_SHORT : + externalType.equals(JavaConstants.TYPE_INT ) ? ClassConstants.TYPE_INT : + externalType.equals(JavaConstants.TYPE_FLOAT ) ? ClassConstants.TYPE_FLOAT : + externalType.equals(JavaConstants.TYPE_LONG ) ? ClassConstants.TYPE_LONG : + externalType.equals(JavaConstants.TYPE_DOUBLE ) ? ClassConstants.TYPE_DOUBLE : + externalType.equals("%" ) ? '%' : + (char)0; String internalType = internalTypeChar != 0 ? String.valueOf(internalTypeChar) : - ClassConstants.INTERNAL_TYPE_CLASS_START + + ClassConstants.TYPE_CLASS_START + internalClassName(externalType) + - ClassConstants.INTERNAL_TYPE_CLASS_END; + ClassConstants.TYPE_CLASS_END; // Prepend the array part, if any. for (int count = 0; count < dimensionCount; count++) { - internalType = ClassConstants.INTERNAL_TYPE_ARRAY + internalType; + internalType = ClassConstants.TYPE_ARRAY + internalType; } return internalType; @@ -646,10 +694,10 @@ public class ClassUtil public static int externalArrayTypeDimensionCount(String externalType) { int dimensions = 0; - int length = ClassConstants.EXTERNAL_TYPE_ARRAY.length(); + int length = JavaConstants.TYPE_ARRAY.length(); int offset = externalType.length() - length; while (externalType.regionMatches(offset, - ClassConstants.EXTERNAL_TYPE_ARRAY, + JavaConstants.TYPE_ARRAY, 0, length)) { @@ -683,29 +731,18 @@ public class ClassUtil char internalTypeChar = internalType.charAt(0); String externalType = - internalTypeChar == ClassConstants.INTERNAL_TYPE_VOID ? - ClassConstants.EXTERNAL_TYPE_VOID : - internalTypeChar == ClassConstants.INTERNAL_TYPE_BOOLEAN ? - ClassConstants.EXTERNAL_TYPE_BOOLEAN : - internalTypeChar == ClassConstants.INTERNAL_TYPE_BYTE ? - ClassConstants.EXTERNAL_TYPE_BYTE : - internalTypeChar == ClassConstants.INTERNAL_TYPE_CHAR ? - ClassConstants.EXTERNAL_TYPE_CHAR : - internalTypeChar == ClassConstants.INTERNAL_TYPE_SHORT ? - ClassConstants.EXTERNAL_TYPE_SHORT : - internalTypeChar == ClassConstants.INTERNAL_TYPE_INT ? - ClassConstants.EXTERNAL_TYPE_INT : - internalTypeChar == ClassConstants.INTERNAL_TYPE_FLOAT ? - ClassConstants.EXTERNAL_TYPE_FLOAT : - internalTypeChar == ClassConstants.INTERNAL_TYPE_LONG ? - ClassConstants.EXTERNAL_TYPE_LONG : - internalTypeChar == ClassConstants.INTERNAL_TYPE_DOUBLE ? - ClassConstants.EXTERNAL_TYPE_DOUBLE : - internalTypeChar == '%' ? - "%" : - internalTypeChar == ClassConstants.INTERNAL_TYPE_CLASS_START ? - externalClassName(internalType.substring(1, internalType.indexOf(ClassConstants.INTERNAL_TYPE_CLASS_END))) : - null; + internalTypeChar == ClassConstants.TYPE_VOID ? JavaConstants.TYPE_VOID : + internalTypeChar == ClassConstants.TYPE_BOOLEAN ? JavaConstants.TYPE_BOOLEAN : + internalTypeChar == ClassConstants.TYPE_BYTE ? JavaConstants.TYPE_BYTE : + internalTypeChar == ClassConstants.TYPE_CHAR ? JavaConstants.TYPE_CHAR : + internalTypeChar == ClassConstants.TYPE_SHORT ? JavaConstants.TYPE_SHORT : + internalTypeChar == ClassConstants.TYPE_INT ? JavaConstants.TYPE_INT : + internalTypeChar == ClassConstants.TYPE_FLOAT ? JavaConstants.TYPE_FLOAT : + internalTypeChar == ClassConstants.TYPE_LONG ? JavaConstants.TYPE_LONG : + internalTypeChar == ClassConstants.TYPE_DOUBLE ? JavaConstants.TYPE_DOUBLE : + internalTypeChar == '%' ? "%" : + internalTypeChar == ClassConstants.TYPE_CLASS_START ? externalClassName(internalType.substring(1, internalType.indexOf(ClassConstants.TYPE_CLASS_END))) : + null; if (externalType == null) { @@ -715,7 +752,7 @@ public class ClassUtil // Append the array part, if any. for (int count = 0; count < dimensionCount; count++) { - externalType += ClassConstants.EXTERNAL_TYPE_ARRAY; + externalType += JavaConstants.TYPE_ARRAY; } return externalType; @@ -732,7 +769,7 @@ public class ClassUtil */ public static boolean isInternalMethodDescriptor(String internalDescriptor) { - return internalDescriptor.charAt(0) == ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN; + return internalDescriptor.charAt(0) == ClassConstants.METHOD_ARGUMENTS_OPEN; } @@ -747,7 +784,7 @@ public class ClassUtil */ public static boolean isExternalMethodNameAndArguments(String externalMemberNameAndArguments) { - return externalMemberNameAndArguments.indexOf(ClassConstants.EXTERNAL_METHOD_ARGUMENTS_OPEN) > 0; + return externalMemberNameAndArguments.indexOf(JavaConstants.METHOD_ARGUMENTS_OPEN) > 0; } @@ -780,7 +817,7 @@ public class ClassUtil String externalMethodNameAndArguments) { StringBuffer internalMethodDescriptor = new StringBuffer(); - internalMethodDescriptor.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN); + internalMethodDescriptor.append(ClassConstants.METHOD_ARGUMENTS_OPEN); ExternalTypeEnumeration externalTypeEnumeration = new ExternalTypeEnumeration(externalMethodNameAndArguments); @@ -790,7 +827,7 @@ public class ClassUtil internalMethodDescriptor.append(internalType(externalTypeEnumeration.nextType())); } - internalMethodDescriptor.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE); + internalMethodDescriptor.append(ClassConstants.METHOD_ARGUMENTS_CLOSE); internalMethodDescriptor.append(internalType(externalReturnType)); return internalMethodDescriptor.toString(); @@ -811,14 +848,14 @@ public class ClassUtil List externalArguments) { StringBuffer internalMethodDescriptor = new StringBuffer(); - internalMethodDescriptor.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN); + internalMethodDescriptor.append(ClassConstants.METHOD_ARGUMENTS_OPEN); for (int index = 0; index < externalArguments.size(); index++) { internalMethodDescriptor.append(internalType((String)externalArguments.get(index))); } - internalMethodDescriptor.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE); + internalMethodDescriptor.append(ClassConstants.METHOD_ARGUMENTS_CLOSE); internalMethodDescriptor.append(internalType(externalReturnType)); return internalMethodDescriptor.toString(); @@ -869,9 +906,9 @@ public class ClassUtil externalMethodReturnTypeAndName(internalClassName, internalMethodName, internalMethodDescriptor) + - ClassConstants.EXTERNAL_METHOD_ARGUMENTS_OPEN + + JavaConstants.METHOD_ARGUMENTS_OPEN + externalMethodArguments(internalMethodDescriptor) + - ClassConstants.EXTERNAL_METHOD_ARGUMENTS_CLOSE; + JavaConstants.METHOD_ARGUMENTS_CLOSE; } @@ -903,48 +940,48 @@ public class ClassUtil StringBuffer string = new StringBuffer(50); - if ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) != 0) + if ((accessFlags & ClassConstants.ACC_PUBLIC) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PUBLIC).append(' '); + string.append(prefix).append(JavaConstants.ACC_PUBLIC).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_PRIVATE) != 0) + if ((accessFlags & ClassConstants.ACC_PRIVATE) != 0) { // Only in InnerClasses attributes. - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PRIVATE).append(' '); + string.append(prefix).append(JavaConstants.ACC_PRIVATE).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_PROTECTED) != 0) + if ((accessFlags & ClassConstants.ACC_PROTECTED) != 0) { // Only in InnerClasses attributes. - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PROTECTED).append(' '); + string.append(prefix).append(JavaConstants.ACC_PROTECTED).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0) + if ((accessFlags & ClassConstants.ACC_STATIC) != 0) { // Only in InnerClasses attributes. - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STATIC).append(' '); + string.append(prefix).append(JavaConstants.ACC_STATIC).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) != 0) + if ((accessFlags & ClassConstants.ACC_FINAL) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_FINAL).append(' '); + string.append(prefix).append(JavaConstants.ACC_FINAL).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_ANNOTATTION) != 0) + if ((accessFlags & ClassConstants.ACC_ANNOTATTION) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ANNOTATION); + string.append(prefix).append(JavaConstants.ACC_ANNOTATION); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_INTERFACE) != 0) + if ((accessFlags & ClassConstants.ACC_INTERFACE) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_INTERFACE).append(' '); + string.append(prefix).append(JavaConstants.ACC_INTERFACE).append(' '); } - else if ((accessFlags & ClassConstants.INTERNAL_ACC_ENUM) != 0) + else if ((accessFlags & ClassConstants.ACC_ENUM) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ENUM).append(' '); + string.append(prefix).append(JavaConstants.ACC_ENUM).append(' '); } - else if ((accessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0) + else if ((accessFlags & ClassConstants.ACC_ABSTRACT) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ABSTRACT).append(' '); + string.append(prefix).append(JavaConstants.ACC_ABSTRACT).append(' '); } - else if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0) + else if ((accessFlags & ClassConstants.ACC_SYNTHETIC) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' '); + string.append(prefix).append(JavaConstants.ACC_SYNTHETIC).append(' '); } return string.toString(); @@ -979,37 +1016,37 @@ public class ClassUtil StringBuffer string = new StringBuffer(50); - if ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) != 0) + if ((accessFlags & ClassConstants.ACC_PUBLIC) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PUBLIC).append(' '); + string.append(prefix).append(JavaConstants.ACC_PUBLIC).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_PRIVATE) != 0) + if ((accessFlags & ClassConstants.ACC_PRIVATE) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PRIVATE).append(' '); + string.append(prefix).append(JavaConstants.ACC_PRIVATE).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_PROTECTED) != 0) + if ((accessFlags & ClassConstants.ACC_PROTECTED) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PROTECTED).append(' '); + string.append(prefix).append(JavaConstants.ACC_PROTECTED).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0) + if ((accessFlags & ClassConstants.ACC_STATIC) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STATIC).append(' '); + string.append(prefix).append(JavaConstants.ACC_STATIC).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) != 0) + if ((accessFlags & ClassConstants.ACC_FINAL) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_FINAL).append(' '); + string.append(prefix).append(JavaConstants.ACC_FINAL).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_VOLATILE) != 0) + if ((accessFlags & ClassConstants.ACC_VOLATILE) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_VOLATILE).append(' '); + string.append(prefix).append(JavaConstants.ACC_VOLATILE).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_TRANSIENT) != 0) + if ((accessFlags & ClassConstants.ACC_TRANSIENT) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_TRANSIENT).append(' '); + string.append(prefix).append(JavaConstants.ACC_TRANSIENT).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0) + if ((accessFlags & ClassConstants.ACC_SYNTHETIC) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' '); + string.append(prefix).append(JavaConstants.ACC_SYNTHETIC).append(' '); } return string.toString(); @@ -1044,53 +1081,100 @@ public class ClassUtil StringBuffer string = new StringBuffer(50); - if ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) != 0) + if ((accessFlags & ClassConstants.ACC_PUBLIC) != 0) + { + string.append(prefix).append(JavaConstants.ACC_PUBLIC).append(' '); + } + if ((accessFlags & ClassConstants.ACC_PRIVATE) != 0) + { + string.append(prefix).append(JavaConstants.ACC_PRIVATE).append(' '); + } + if ((accessFlags & ClassConstants.ACC_PROTECTED) != 0) + { + string.append(prefix).append(JavaConstants.ACC_PROTECTED).append(' '); + } + if ((accessFlags & ClassConstants.ACC_STATIC) != 0) + { + string.append(prefix).append(JavaConstants.ACC_STATIC).append(' '); + } + if ((accessFlags & ClassConstants.ACC_FINAL) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PUBLIC).append(' '); + string.append(prefix).append(JavaConstants.ACC_FINAL).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_PRIVATE) != 0) + if ((accessFlags & ClassConstants.ACC_SYNCHRONIZED) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PRIVATE).append(' '); + string.append(prefix).append(JavaConstants.ACC_SYNCHRONIZED).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_PROTECTED) != 0) + if ((accessFlags & ClassConstants.ACC_BRIDGE) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PROTECTED).append(' '); + string.append(prefix).append(JavaConstants.ACC_BRIDGE).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0) + if ((accessFlags & ClassConstants.ACC_VARARGS) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STATIC).append(' '); + string.append(prefix).append(JavaConstants.ACC_VARARGS).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) != 0) + if ((accessFlags & ClassConstants.ACC_NATIVE) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_FINAL).append(' '); + string.append(prefix).append(JavaConstants.ACC_NATIVE).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNCHRONIZED) != 0) + if ((accessFlags & ClassConstants.ACC_ABSTRACT) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED).append(' '); + string.append(prefix).append(JavaConstants.ACC_ABSTRACT).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_BRIDGE) != 0) + if ((accessFlags & ClassConstants.ACC_STRICT) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_BRIDGE).append(' '); + string.append(prefix).append(JavaConstants.ACC_STRICT).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_VARARGS) != 0) + if ((accessFlags & ClassConstants.ACC_SYNTHETIC) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_VARARGS).append(' '); + string.append(prefix).append(JavaConstants.ACC_SYNTHETIC).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_NATIVE) != 0) + + return string.toString(); + } + + + /** + * Converts internal method parameter access flags into an external access + * description. + * @param accessFlags the method parameter access flags. + * @return the external method parameter access description, + * e.g. "<code>final mandated </code>". + */ + public static String externalParameterAccessFlags(int accessFlags) + { + return externalParameterAccessFlags(accessFlags, ""); + } + + + /** + * Converts internal method parameter access flags into an external access + * description. + * @param accessFlags the method parameter access flags. + * @param prefix a prefix that is added to each access modifier. + * @return the external method parameter access description, + * e.g. "final mandated ". + */ + public static String externalParameterAccessFlags(int accessFlags, String prefix) + { + if (accessFlags == 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_NATIVE).append(' '); + return EMPTY_STRING; } - if ((accessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0) + + StringBuffer string = new StringBuffer(50); + + if ((accessFlags & ClassConstants.ACC_FINAL) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ABSTRACT).append(' '); + string.append(prefix).append(JavaConstants.ACC_FINAL).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_STRICT) != 0) + if ((accessFlags & ClassConstants.ACC_SYNTHETIC) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STRICT).append(' '); + string.append(prefix).append(JavaConstants.ACC_SYNTHETIC).append(' '); } - if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0) + if ((accessFlags & ClassConstants.ACC_MANDATED) != 0) { - string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' '); + string.append(prefix).append(JavaConstants.ACC_MANDATED).append(' '); } return string.toString(); @@ -1128,7 +1212,7 @@ public class ClassUtil String internalMethodName, String internalMethodDescriptor) { - return internalMethodName.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ? + return internalMethodName.equals(ClassConstants.METHOD_NAME_INIT) ? externalShortClassName(externalClassName(internalClassName)) : (externalMethodReturnType(internalMethodDescriptor) + ' ' + @@ -1156,7 +1240,7 @@ public class ClassUtil externalMethodNameAndArguments.append(externalType(internalTypeEnumeration.nextType())); if (internalTypeEnumeration.hasMoreTypes()) { - externalMethodNameAndArguments.append(ClassConstants.EXTERNAL_METHOD_ARGUMENTS_SEPARATOR); + externalMethodNameAndArguments.append(JavaConstants.METHOD_ARGUMENTS_SEPARATOR); } } @@ -1190,7 +1274,7 @@ public class ClassUtil */ public static String internalPackagePrefix(String internalClassName) { - return internalClassName.substring(0, internalClassName.lastIndexOf(ClassConstants.INTERNAL_PACKAGE_SEPARATOR, + return internalClassName.substring(0, internalClassName.lastIndexOf(ClassConstants.PACKAGE_SEPARATOR, internalClassName.length() - 2) + 1); } @@ -1221,7 +1305,7 @@ public class ClassUtil */ public static String externalPackagePrefix(String externalClassName) { - return externalClassName.substring(0, externalClassName.lastIndexOf(ClassConstants.EXTERNAL_PACKAGE_SEPARATOR, + return externalClassName.substring(0, externalClassName.lastIndexOf(JavaConstants.PACKAGE_SEPARATOR, externalClassName.length() - 2) + 1); } } diff --git a/src/proguard/classfile/util/DescriptorClassEnumeration.java b/src/proguard/classfile/util/DescriptorClassEnumeration.java index 81590fa..b15d470 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.util; -import proguard.classfile.ClassConstants; +import proguard.classfile.*; import java.util.Stack; @@ -58,6 +58,8 @@ public class DescriptorClassEnumeration { int count = 0; + reset(); + nextFluff(); while (hasMoreClassNames()) { @@ -67,13 +69,26 @@ public class DescriptorClassEnumeration nextFluff(); } - index = 0; + reset(); return count; } /** + * Resets the enumeration. + */ + private void reset() + { + index = 0; + nestingLevel = 0; + isInnerClassName = false; + accumulatedClassName = null; + accumulatedClassNames = null; + } + + + /** * Returns whether the enumeration can provide more class names from the * descriptor. */ @@ -95,7 +110,7 @@ public class DescriptorClassEnumeration { switch (descriptor.charAt(index++)) { - case ClassConstants.INTERNAL_TYPE_GENERIC_START: + case ClassConstants.TYPE_GENERIC_START: { nestingLevel++; @@ -110,7 +125,7 @@ public class DescriptorClassEnumeration break; } - case ClassConstants.INTERNAL_TYPE_GENERIC_END: + case ClassConstants.TYPE_GENERIC_END: { nestingLevel--; @@ -120,42 +135,42 @@ public class DescriptorClassEnumeration continue loop; } - case ClassConstants.INTERNAL_TYPE_GENERIC_BOUND: + case ClassConstants.TYPE_GENERIC_BOUND: { continue loop; } - case ClassConstants.INTERNAL_TYPE_CLASS_START: + case ClassConstants.TYPE_CLASS_START: { // We've found the start of an ordinary class name. nestingLevel += 2; isInnerClassName = false; break loop; } - case ClassConstants.INTERNAL_TYPE_CLASS_END: + case ClassConstants.TYPE_CLASS_END: { nestingLevel -= 2; break; } - case ClassConstants.EXTERNAL_INNER_CLASS_SEPARATOR: + case JavaConstants.INNER_CLASS_SEPARATOR: { // We've found the start of an inner class name in a signature. isInnerClassName = true; break loop; } - case ClassConstants.INTERNAL_TYPE_GENERIC_VARIABLE_START: + case ClassConstants.TYPE_GENERIC_VARIABLE_START: { // We've found the start of a type identifier. Skip to the end. - while (descriptor.charAt(index++) != ClassConstants.INTERNAL_TYPE_CLASS_END); + while (descriptor.charAt(index++) != ClassConstants.TYPE_CLASS_END); break; } } if (nestingLevel == 1 && - descriptor.charAt(index) != ClassConstants.INTERNAL_TYPE_GENERIC_END) + descriptor.charAt(index) != ClassConstants.TYPE_GENERIC_END) { // We're at the start of a type parameter. Skip to the start // of the bounds. - while (descriptor.charAt(index++) != ClassConstants.INTERNAL_TYPE_GENERIC_BOUND); + while (descriptor.charAt(index++) != ClassConstants.TYPE_GENERIC_BOUND); } } @@ -175,9 +190,9 @@ public class DescriptorClassEnumeration { switch (descriptor.charAt(index)) { - case ClassConstants.INTERNAL_TYPE_GENERIC_START: - case ClassConstants.INTERNAL_TYPE_CLASS_END: - case ClassConstants.EXTERNAL_INNER_CLASS_SEPARATOR: + case ClassConstants.TYPE_GENERIC_START: + case ClassConstants.TYPE_CLASS_END: + case JavaConstants.INNER_CLASS_SEPARATOR: { break loop; } @@ -190,7 +205,7 @@ public class DescriptorClassEnumeration // Recompose the inner class name if necessary. accumulatedClassName = isInnerClassName ? - accumulatedClassName + ClassConstants.INTERNAL_INNER_CLASS_SEPARATOR + className : + accumulatedClassName + ClassConstants.INNER_CLASS_SEPARATOR + className : className; return accumulatedClassName; diff --git a/src/proguard/classfile/util/DynamicClassReferenceInitializer.java b/src/proguard/classfile/util/DynamicClassReferenceInitializer.java index 865e094..413d885 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -66,21 +66,21 @@ implements InstructionVisitor, 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_METHOD_NAME_CLASS_FOR_NAME), - new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_FOR_NAME), + new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS), + new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_FOR_NAME), + new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_FOR_NAME), // 6 new MethodrefConstant(1, 7, null, null), new NameAndTypeConstant(8, 9), - new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_INSTANCE), - new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_INSTANCE), + new Utf8Constant(ClassConstants.METHOD_NAME_NEW_INSTANCE), + new Utf8Constant(ClassConstants.METHOD_TYPE_NEW_INSTANCE), // 10 new MethodrefConstant(1, 11, null, null), new NameAndTypeConstant(12, 13), - new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_CLASS_GET_COMPONENT_TYPE), - new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_COMPONENT_TYPE), + new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_GET_COMPONENT_TYPE), + new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_GET_COMPONENT_TYPE), }; // Class.forName("SomeClass"). @@ -103,15 +103,15 @@ implements InstructionVisitor, // { // new MethodrefConstant(A, 1, null, null), // new NameAndTypeConstant(2, 3), -// new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_DOT_CLASS_JAVAC), -// new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_DOT_CLASS_JAVAC), +// new Utf8Constant(ClassConstants.METHOD_NAME_DOT_CLASS_JAVAC), +// new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JAVAC), // }; private final Constant[] DOT_CLASS_JAVAC_CONSTANTS = new Constant[] { new MethodrefConstant(A, 1, null, null), new NameAndTypeConstant(B, 2), - new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_DOT_CLASS_JAVAC), + new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JAVAC), }; // SomeClass.class = class$("SomeClass") (javac). @@ -126,15 +126,15 @@ implements InstructionVisitor, // { // new MethodrefConstant(A, 1, null, null), // new NameAndTypeConstant(2, 3), -// new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_DOT_CLASS_JIKES), -// new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_DOT_CLASS_JIKES), +// new Utf8Constant(ClassConstants.METHOD_NAME_DOT_CLASS_JIKES), +// new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JIKES), // }; private final Constant[] DOT_CLASS_JIKES_CONSTANTS = new Constant[] { new MethodrefConstant(A, 1, null, null), new NameAndTypeConstant(B, 2), - new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_DOT_CLASS_JIKES), + new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JIKES), }; // SomeClass.class = class("SomeClass", false) (jikes). @@ -240,6 +240,19 @@ implements InstructionVisitor, public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) { + // Try to match the (SomeClass)Class.forName(someName).newInstance() + // construct. Apply this matcher first, so the next matcher can still + // reset it after the first instruction. + instruction.accept(clazz, method, codeAttribute, offset, + classForNameCastMatcher); + + // Did we find a match? + if (classForNameCastMatcher.isMatching()) + { + // Print out a note about the construct. + clazz.constantPoolEntryAccept(classForNameCastMatcher.matchedConstantIndex(X), this); + } + // Try to match the Class.forName("SomeClass") construct. instruction.accept(clazz, method, codeAttribute, offset, constantClassForNameMatcher); @@ -254,18 +267,6 @@ implements InstructionVisitor, classForNameCastMatcher.reset(); } - // Try to match the (SomeClass)Class.forName(someName).newInstance() - // construct. - instruction.accept(clazz, method, codeAttribute, offset, - classForNameCastMatcher); - - // Did we find a match? - if (classForNameCastMatcher.isMatching()) - { - // Print out a note about the construct. - clazz.constantPoolEntryAccept(classForNameCastMatcher.matchedConstantIndex(X), this); - } - // Try to match the javac .class construct. instruction.accept(clazz, method, codeAttribute, offset, dotClassJavacMatcher); @@ -336,15 +337,15 @@ implements InstructionVisitor, String methodType = methodrefConstant.getType(clazz); // Do the method's class and type match? - if (methodType.equals(ClassConstants.INTERNAL_METHOD_TYPE_DOT_CLASS_JAVAC) || - methodType.equals(ClassConstants.INTERNAL_METHOD_TYPE_DOT_CLASS_JIKES)) + if (methodType.equals(ClassConstants.METHOD_TYPE_DOT_CLASS_JAVAC) || + methodType.equals(ClassConstants.METHOD_TYPE_DOT_CLASS_JIKES)) { String methodName = methodrefConstant.getName(clazz); // Does the method's name match one of the special names? isClassForNameInvocation = - methodName.equals(ClassConstants.INTERNAL_METHOD_NAME_DOT_CLASS_JAVAC) || - methodName.equals(ClassConstants.INTERNAL_METHOD_NAME_DOT_CLASS_JIKES); + methodName.equals(ClassConstants.METHOD_NAME_DOT_CLASS_JAVAC) || + methodName.equals(ClassConstants.METHOD_NAME_DOT_CLASS_JIKES); if (isClassForNameInvocation) { diff --git a/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java b/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java index 23c8d40..e35063c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ package proguard.classfile.util; import proguard.classfile.*; import proguard.classfile.attribute.CodeAttribute; -import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.constant.*; import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.instruction.*; @@ -54,10 +53,10 @@ implements InstructionVisitor, ConstantVisitor, MemberVisitor { - /* - private static boolean DEBUG = true; - /*/ + //* private static final boolean DEBUG = false; + /*/ + private static boolean DEBUG = true; //*/ public static final int CLASS_INDEX = InstructionSequenceMatcher.X; @@ -75,9 +74,9 @@ implements InstructionVisitor, 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_METHOD_NAME_CLASS_GET_FIELD), - new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_FIELD), + new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS), + new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_GET_FIELD), + new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_GET_FIELD), }; private final Constant[] GET_DECLARED_FIELD_CONSTANTS = new Constant[] @@ -85,9 +84,9 @@ implements InstructionVisitor, 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_METHOD_NAME_CLASS_GET_DECLARED_FIELD), - new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_FIELD), + new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS), + new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_GET_DECLARED_FIELD), + new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_GET_DECLARED_FIELD), }; private final Constant[] GET_CONSTRUCTOR_CONSTANTS = new Constant[] @@ -95,9 +94,9 @@ implements InstructionVisitor, 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), + new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS), + new Utf8Constant(ClassConstants.CONSTRUCTOR_NAME_CLASS_GET_CONSTRUCTOR), + new Utf8Constant(ClassConstants.CONSTRUCTOR_TYPE_CLASS_GET_CONSTRUCTOR), }; private final Constant[] GET_DECLARED_CONSTRUCTOR_CONSTANTS = new Constant[] @@ -105,9 +104,9 @@ implements InstructionVisitor, 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), + new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS), + new Utf8Constant(ClassConstants.CONSTRUCTOR_NAME_CLASS_GET_DECLARED_CONSTRUCTOR), + new Utf8Constant(ClassConstants.CONSTRUCTOR_TYPE_CLASS_GET_DECLARED_CONSTRUCTOR), }; private final Constant[] GET_METHOD_CONSTANTS = new Constant[] @@ -115,9 +114,9 @@ implements InstructionVisitor, 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_METHOD_NAME_CLASS_GET_METHOD), - new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_METHOD), + new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS), + new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_GET_METHOD), + new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_GET_METHOD), }; private final Constant[] GET_DECLARED_METHOD_CONSTANTS = new Constant[] @@ -125,9 +124,9 @@ implements InstructionVisitor, 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_METHOD_NAME_CLASS_GET_DECLARED_METHOD), - new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_METHOD), + new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS), + new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_GET_DECLARED_METHOD), + new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_GET_DECLARED_METHOD), }; private final Constant[] NEW_INTEGER_UPDATER_CONSTANTS = new Constant[] @@ -135,9 +134,9 @@ implements InstructionVisitor, 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), + new Utf8Constant(ClassConstants.NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER), + new Utf8Constant(ClassConstants.METHOD_NAME_NEW_UPDATER), + new Utf8Constant(ClassConstants.METHOD_TYPE_NEW_INTEGER_UPDATER), }; private final Constant[] NEW_LONG_UPDATER_CONSTANTS = new Constant[] @@ -145,9 +144,9 @@ implements InstructionVisitor, 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), + new Utf8Constant(ClassConstants.NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_LONG_FIELD_UPDATER), + new Utf8Constant(ClassConstants.METHOD_NAME_NEW_UPDATER), + new Utf8Constant(ClassConstants.METHOD_TYPE_NEW_LONG_UPDATER), }; private final Constant[] NEW_REFERENCE_UPDATER_CONSTANTS = new Constant[] @@ -155,9 +154,9 @@ implements InstructionVisitor, 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), + new Utf8Constant(ClassConstants.NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_REFERENCE_FIELD_UPDATER), + new Utf8Constant(ClassConstants.METHOD_NAME_NEW_UPDATER), + new Utf8Constant(ClassConstants.METHOD_TYPE_NEW_REFERENCE_UPDATER), }; // SomeClass.class.get[Declared]Field("someField"). @@ -549,42 +548,42 @@ implements InstructionVisitor, // matchGetMember(clazz, method, codeAttribute, offset, instruction, // cnull, //onstantGetConstructorMatcher0, // getConstructorMatcher0, false, false, -// ClassConstants.INTERNAL_METHOD_NAME_INIT, null); +// ClassConstants.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); +// ClassConstants.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); + ClassConstants.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); + ClassConstants.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); + ClassConstants.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); + ClassConstants.METHOD_NAME_INIT, null); // Try to match the SomeClass.class.getMethod("someMethod", new Class[] // {}) construct. @@ -627,14 +626,14 @@ implements InstructionVisitor, matchGetMember(clazz, method, codeAttribute, offset, instruction, constantGetIntegerUpdaterMatcher, getIntegerUpdaterMatcher, true, false, null, - "" + ClassConstants.INTERNAL_TYPE_INT); + "" + ClassConstants.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); + "" + ClassConstants.TYPE_LONG); // Try to match the AtomicReferenceFieldUpdater.newUpdater( // SomeClass.class, SomeClass.class, "someField") construct. @@ -840,7 +839,7 @@ implements InstructionVisitor, " accesses a " + (isDeclared ? "declared " : "") + (isField ? "field" : - memberName.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ? + memberName.equals(ClassConstants.METHOD_NAME_INIT) ? "constructor" : "method") + " '" + externalMemberDescription + diff --git a/src/proguard/classfile/util/EnumFieldReferenceInitializer.java b/src/proguard/classfile/util/EnumFieldReferenceInitializer.java index dae6db2..c856893 100644 --- a/src/proguard/classfile/util/EnumFieldReferenceInitializer.java +++ b/src/proguard/classfile/util/EnumFieldReferenceInitializer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,13 +24,12 @@ 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.attribute.visitor.AllAttributeVisitor; 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; +import proguard.classfile.visitor.MemberVisitor; /** * This ElementValueVisitor initializes the field references of the @@ -44,10 +43,10 @@ implements ElementValueVisitor, InstructionVisitor, ConstantVisitor { - /* - private static boolean DEBUG = true; - /*/ + //* private static final boolean DEBUG = false; + /*/ + private static boolean DEBUG = true; //*/ private MemberVisitor enumFieldFinder = new AllAttributeVisitor( @@ -80,8 +79,8 @@ implements ElementValueVisitor, enumTypeName = enumConstantElementValue.getTypeName(clazz); enumConstantName = enumConstantElementValue.getConstantName(clazz); referencedEnumField = null; - referencedEnumClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT, - ClassConstants.INTERNAL_METHOD_TYPE_CLINIT, + referencedEnumClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT, + ClassConstants.METHOD_TYPE_CLINIT, enumFieldFinder); // Otherwise try to find the enum field through its name. diff --git a/src/proguard/classfile/util/ExternalTypeEnumeration.java b/src/proguard/classfile/util/ExternalTypeEnumeration.java index e5b7067..b96a80e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.util; -import proguard.classfile.ClassConstants; +import proguard.classfile.*; /** @@ -61,7 +61,7 @@ public class ExternalTypeEnumeration public void reset() { - index = descriptor.indexOf(ClassConstants.EXTERNAL_METHOD_ARGUMENTS_OPEN) + 1; + index = descriptor.indexOf(JavaConstants.METHOD_ARGUMENTS_OPEN) + 1; if (index < 1) { @@ -81,13 +81,13 @@ public class ExternalTypeEnumeration int startIndex = index; // Find the next separating comma. - index = descriptor.indexOf(ClassConstants.EXTERNAL_METHOD_ARGUMENTS_SEPARATOR, + index = descriptor.indexOf(JavaConstants.METHOD_ARGUMENTS_SEPARATOR, startIndex); // Otherwise find the closing parenthesis. if (index < 0) { - index = descriptor.indexOf(ClassConstants.EXTERNAL_METHOD_ARGUMENTS_CLOSE, + index = descriptor.indexOf(JavaConstants.METHOD_ARGUMENTS_CLOSE, startIndex); if (index < 0) { @@ -101,6 +101,6 @@ public class ExternalTypeEnumeration public String methodName() { - return descriptor.substring(0, descriptor.indexOf(ClassConstants.EXTERNAL_METHOD_ARGUMENTS_OPEN)).trim(); + return descriptor.substring(0, descriptor.indexOf(JavaConstants.METHOD_ARGUMENTS_OPEN)).trim(); } } diff --git a/src/proguard/classfile/util/InstructionSequenceMatcher.java b/src/proguard/classfile/util/InstructionSequenceMatcher.java index 8c529a9..dc021ee 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,12 +41,12 @@ extends SimplifiedVisitor implements InstructionVisitor, ConstantVisitor { - /* - public static boolean DEBUG = true; - public static boolean DEBUG_MORE = true; - /*/ + //* private static final boolean DEBUG = false; private static final boolean DEBUG_MORE = false; + /*/ + public static boolean DEBUG = true; + public static boolean DEBUG_MORE = true; //*/ public static final int X = 0x40000000; diff --git a/src/proguard/classfile/util/InternalTypeEnumeration.java b/src/proguard/classfile/util/InternalTypeEnumeration.java index 9c63ad9..53538d1 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +45,8 @@ public class InternalTypeEnumeration public InternalTypeEnumeration(String descriptor) { this.descriptor = descriptor; - this.firstIndex = descriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN); - this.lastIndex = descriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE); + this.firstIndex = descriptor.indexOf(ClassConstants.METHOD_ARGUMENTS_OPEN); + this.lastIndex = descriptor.indexOf(ClassConstants.METHOD_ARGUMENTS_CLOSE); this.index = firstIndex + 1; if (lastIndex < 0) @@ -57,6 +57,15 @@ public class InternalTypeEnumeration /** + * Returns whether the type is a method signature. + */ + public boolean isMethodSignature() + { + return firstIndex >= 0; + } + + + /** * Returns the formal type parameters from the descriptor, assuming it's a * method descriptor. */ @@ -88,13 +97,13 @@ public class InternalTypeEnumeration char c = descriptor.charAt(index++); switch (c) { - case ClassConstants.INTERNAL_TYPE_CLASS_START: - case ClassConstants.INTERNAL_TYPE_GENERIC_VARIABLE_START: + case ClassConstants.TYPE_CLASS_START: + case ClassConstants.TYPE_GENERIC_VARIABLE_START: { skipClass(); break; } - case ClassConstants.INTERNAL_TYPE_GENERIC_START: + case ClassConstants.TYPE_GENERIC_START: { skipGeneric(); break; @@ -119,7 +128,7 @@ public class InternalTypeEnumeration private void skipArray() { - while (descriptor.charAt(index) == ClassConstants.INTERNAL_TYPE_ARRAY) + while (descriptor.charAt(index) == ClassConstants.TYPE_ARRAY) { index++; } @@ -133,11 +142,11 @@ public class InternalTypeEnumeration char c = descriptor.charAt(index++); switch (c) { - case ClassConstants.INTERNAL_TYPE_GENERIC_START: + case ClassConstants.TYPE_GENERIC_START: skipGeneric(); break; - case ClassConstants.INTERNAL_TYPE_CLASS_END: + case ClassConstants.TYPE_CLASS_END: return; } } @@ -153,11 +162,11 @@ public class InternalTypeEnumeration char c = descriptor.charAt(index++); switch (c) { - case ClassConstants.INTERNAL_TYPE_GENERIC_START: + case ClassConstants.TYPE_GENERIC_START: nestingLevel++; break; - case ClassConstants.INTERNAL_TYPE_GENERIC_END: + case ClassConstants.TYPE_GENERIC_END: nestingLevel--; break; } diff --git a/src/proguard/classfile/util/MemberFinder.java b/src/proguard/classfile/util/MemberFinder.java index 36c0003..dc2724e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -126,7 +126,7 @@ implements MemberVisitor clazz.hierarchyAccept(false, false, false, true, new NamedMethodVisitor(name, descriptor, - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, this))); + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, this))); } catch (MemberFoundException ex) { @@ -155,7 +155,7 @@ implements MemberVisitor this.member = null; clazz.hierarchyAccept(false, false, false, true, new NamedFieldVisitor(name, descriptor, - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, this))); + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, this))); } catch (MemberFoundException ex) { diff --git a/src/proguard/classfile/util/MethodLinker.java b/src/proguard/classfile/util/MethodLinker.java index 56b6723..4b4afa2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,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 | ClassConstants.INTERNAL_ACC_STATIC, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC, this))); // Clean up for the next class hierarchy. @@ -69,8 +69,7 @@ implements ClassVisitor, // Special cases: <clinit> and <init> are always kept unchanged. // We can ignore them here. - if (name.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) || - name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + if (ClassUtil.isInitializer(name)) { return; } diff --git a/src/proguard/classfile/util/SimplifiedVisitor.java b/src/proguard/classfile/util/SimplifiedVisitor.java index aed46eb..e662061 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.util; import proguard.classfile.*; import proguard.classfile.attribute.*; import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.target.*; import proguard.classfile.attribute.preverification.*; import proguard.classfile.constant.*; import proguard.classfile.instruction.*; @@ -357,6 +358,12 @@ public abstract class SimplifiedVisitor } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + visitAnyAttribute(clazz, methodParametersAttribute); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { visitAnyAttribute(clazz, exceptionsAttribute); @@ -483,6 +490,81 @@ public abstract class SimplifiedVisitor } + /** + * Visits any type of TypeAnnotationsAttribute of a class. + */ + public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) + { + visitAnyAnnotationsAttribute(clazz, typeAnnotationsAttribute); + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + visitAnyTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute); + } + + + /** + * Visits the given RuntimeVisibleTypeAnnotationsAttribute of any type of class member. + */ + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Member member, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + visitRuntimeVisibleTypeAnnotationsAttribute(clazz, (Member)field, runtimeVisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + visitRuntimeVisibleTypeAnnotationsAttribute(clazz, (Member)method, runtimeVisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + visitAnyTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute); + } + + + /** + * Visits the given RuntimeInvisibleTypeAnnotationsAttribute of any type of class member. + */ + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Member member, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, (Member)field, runtimeInvisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, (Member)method, runtimeInvisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute); + } + + public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) { visitAnyAttribute(clazz, annotationDefaultAttribute); @@ -795,8 +877,206 @@ public abstract class SimplifiedVisitor } + public void visitAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, Annotation annotation) + { + visitAnnotation(clazz, method, annotation); + } + + + // Simplifications for TypeAnnotationVisitor. + + public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) + { + throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called"); + } + + + /** + * Visits the given TypeAnnotation of any type of class member. + */ + public void visitTypeAnnotation(Clazz clazz, Member member, TypeAnnotation typeAnnotation) + { + visitTypeAnnotation(clazz, typeAnnotation); + } + + + public void visitTypeAnnotation(Clazz clazz, Field field, TypeAnnotation typeAnnotation) + { + visitTypeAnnotation(clazz, (Member)field, typeAnnotation); + } + + + public void visitTypeAnnotation(Clazz clazz, Method method, TypeAnnotation typeAnnotation) + { + visitTypeAnnotation(clazz, (Member)method, typeAnnotation); + } + + + public void visitTypeAnnotation(Clazz clazz, Method method, int parameterIndex, TypeAnnotation typeAnnotation) + { + visitTypeAnnotation(clazz, method, typeAnnotation); + } + + + public void visitTypeAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation) + { + visitTypeAnnotation(clazz, method, typeAnnotation); + } + + + // Simplifications for TargetInfoVisitor. + + /** + * Visits any type of TargetInfo. + */ + public void visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo) + { + throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called"); + } + + + public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo) + { + visitAnyTargetInfo(clazz, typeAnnotation, typeParameterTargetInfo); + } + + + public void visitTypeParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo) + { + visitTypeParameterTargetInfo(clazz, typeAnnotation, typeParameterTargetInfo); + } + + + public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo) + { + visitAnyTargetInfo(clazz, typeAnnotation, superTypeTargetInfo); + } + + + public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo) + { + visitAnyTargetInfo(clazz, typeAnnotation, typeParameterBoundTargetInfo); + } + + + /** + * Visits the given TypeParameterBoundTargetInfo of any type of class member. + */ + public void visitTypeParameterBoundTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo) + { + visitTypeParameterBoundTargetInfo(clazz, typeAnnotation, typeParameterBoundTargetInfo); + } + + + public void visitTypeParameterBoundTargetInfo(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo) + { + visitTypeParameterBoundTargetInfo(clazz, (Member)field, typeAnnotation, typeParameterBoundTargetInfo); + } + + + public void visitTypeParameterBoundTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo) + { + visitTypeParameterBoundTargetInfo(clazz, (Member)method, typeAnnotation, typeParameterBoundTargetInfo); + } + + + /** + * Visits the given EmptyTargetInfo of any type of class member. + */ + public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo) + { + visitAnyTargetInfo(clazz, typeAnnotation, emptyTargetInfo); + } + + + public void visitEmptyTargetInfo(Clazz clazz, Field field, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo) + { + visitEmptyTargetInfo(clazz, (Member)field, typeAnnotation, emptyTargetInfo); + } + + + public void visitEmptyTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo) + { + visitEmptyTargetInfo(clazz, (Member)method, typeAnnotation, emptyTargetInfo); + } + + + public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo) + { + visitAnyTargetInfo(clazz, typeAnnotation, formalParameterTargetInfo); + } + + + public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo) + { + visitAnyTargetInfo(clazz, typeAnnotation, throwsTargetInfo); + } + + + public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) + { + visitAnyTargetInfo(clazz, typeAnnotation, localVariableTargetInfo); + } + + + public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo) + { + visitAnyTargetInfo(clazz, typeAnnotation, catchTargetInfo); + } + + + public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo) + { + visitAnyTargetInfo(clazz, typeAnnotation, offsetTargetInfo); + } + + + public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo) + { + visitAnyTargetInfo(clazz, typeAnnotation, typeArgumentTargetInfo); + } + + + // Simplifications for TypePathInfoVisitor. + + public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo) + { + throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called"); + } + + + /** + * Visits the given TypePathInfo of any type of class member. + */ + public void visitTypePathInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo) + { + visitTypePathInfo(clazz, typeAnnotation, typePathInfo); + } + + + public void visitTypePathInfo(Clazz clazz, Field field, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo) + { + visitTypePathInfo(clazz, (Member)field, typeAnnotation, typePathInfo); + } + + + public void visitTypePathInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo) + { + visitTypePathInfo(clazz, (Member)method, typeAnnotation, typePathInfo); + } + + + public void visitTypePathInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo) + { + visitTypePathInfo(clazz, method, typeAnnotation, typePathInfo); + } + + // Simplifications for ElementValueVisitor. + /** + * Visits any type of ElementValue. + */ public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) { throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called"); diff --git a/src/proguard/classfile/util/StringReferenceInitializer.java b/src/proguard/classfile/util/StringReferenceInitializer.java index f00f0d3..4d96aa4 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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/StringSharer.java b/src/proguard/classfile/util/StringSharer.java index dacb2d1..5ef231e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/util/WarningPrinter.java b/src/proguard/classfile/util/WarningPrinter.java index 39172dd..4f5c477 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 5c6f3de..20c6349 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 92c4b05..1860202 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 ab26bf3..c73df62 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 5d8e6a3..a5d97e7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 e094ce3..cf3244e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 1855662..09af6d9 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 a7ad1f6..bf20866 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,11 +43,16 @@ implements ClassVisitor, ConstantVisitor, MemberVisitor, AttributeVisitor, + BootstrapMethodInfoVisitor, ExceptionInfoVisitor, InnerClassesInfoVisitor, StackMapFrameVisitor, VerificationTypeVisitor, + ParameterInfoVisitor, + LocalVariableInfoVisitor, + LocalVariableTypeInfoVisitor, AnnotationVisitor, + TypeAnnotationVisitor, ElementValueVisitor { // Implementations for ClassVisitor. @@ -106,6 +111,14 @@ implements ClassVisitor, } + public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute) + { + clean(bootstrapMethodsAttribute); + + bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this); + } + + public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) { clean(innerClassesAttribute); @@ -114,6 +127,14 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + clean(methodParametersAttribute); + + methodParametersAttribute.parametersAccept(clazz, method, this); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { clean(exceptionsAttribute); @@ -147,6 +168,22 @@ implements ClassVisitor, } + public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) + { + clean(localVariableTableAttribute); + + localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); + } + + + public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) + { + clean(localVariableTypeTableAttribute); + + localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); + } + + public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) { clean(annotationsAttribute); @@ -163,6 +200,14 @@ implements ClassVisitor, } + public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) + { + clean(typeAnnotationsAttribute); + + typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this); + } + + public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) { clean(annotationDefaultAttribute); @@ -171,6 +216,14 @@ implements ClassVisitor, } + // Implementations for BootstrapMethodInfoVisitor. + + public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo) + { + clean(bootstrapMethodInfo); + } + + // Implementations for InnerClassesInfoVisitor. public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) @@ -234,6 +287,30 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + clean(parameterInfo); + } + + + // Implementations for LocalVariableInfoVisitor. + + public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) + { + clean(localVariableInfo); + } + + + // Implementations for LocalVariableTypeInfoVisitor. + + public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) + { + clean(localVariableTypeInfo); + } + + // Implementations for AnnotationVisitor. public void visitAnnotation(Clazz clazz, Annotation annotation) @@ -244,6 +321,18 @@ implements ClassVisitor, } + // Implementations for TypeAnnotationVisitor. + + public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) + { + clean(typeAnnotation); + + //typeAnnotation.targetInfoAccept(clazz, this); + //typeAnnotation.typePathInfosAccept(clazz, this); + typeAnnotation.elementValuesAccept(clazz, this); + } + + // Implementations for ElementValueVisitor. public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) diff --git a/src/proguard/classfile/visitor/ClassCollector.java b/src/proguard/classfile/visitor/ClassCollector.java index a24bb0b..05bb23b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 b6deef2..835f0bd 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 38ba3d6..d459719 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 bd66eb1..3415faa 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/visitor/ClassPoolFiller.java b/src/proguard/classfile/visitor/ClassPoolFiller.java index ae234be..bd66a7d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 821304a..a91a69d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 0c55d1d..42df828 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 3121e58..9af8f75 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -23,6 +23,8 @@ package proguard.classfile.visitor; import proguard.classfile.*; import proguard.classfile.attribute.*; import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.target.*; +import proguard.classfile.attribute.annotation.target.visitor.*; import proguard.classfile.attribute.annotation.visitor.*; import proguard.classfile.attribute.preverification.*; import proguard.classfile.attribute.preverification.visitor.*; @@ -54,9 +56,14 @@ implements ClassVisitor, StackMapFrameVisitor, VerificationTypeVisitor, LineNumberInfoVisitor, + ParameterInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, + TypeAnnotationVisitor, + TargetInfoVisitor, + LocalVariableTargetElementVisitor, + TypePathInfoVisitor, ElementValueVisitor, InstructionVisitor { @@ -100,10 +107,10 @@ implements ClassVisitor, println(" = target " + ClassUtil.externalClassVersion(programClass.u4version)); println("Access flags: 0x" + Integer.toHexString(programClass.u2accessFlags)); println(" = " + - ((programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ANNOTATTION) != 0 ? "@ " : "") + + ((programClass.u2accessFlags & ClassConstants.ACC_ANNOTATTION) != 0 ? "@ " : "") + ClassUtil.externalClassAccessFlags(programClass.u2accessFlags) + - ((programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ENUM) != 0 ? "enum " : - (programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_INTERFACE) == 0 ? "class " : + ((programClass.u2accessFlags & ClassConstants.ACC_ENUM) != 0 ? "enum " : + (programClass.u2accessFlags & ClassConstants.ACC_INTERFACE) == 0 ? "class " : "") + ClassUtil.externalClassName(programClass.getName()) + (programClass.u2superClass == 0 ? "" : " extends " + @@ -152,10 +159,10 @@ implements ClassVisitor, println("Superclass: " + libraryClass.getSuperName()); println("Access flags: 0x" + Integer.toHexString(libraryClass.u2accessFlags)); println(" = " + - ((libraryClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ANNOTATTION) != 0 ? "@ " : "") + + ((libraryClass.u2accessFlags & ClassConstants.ACC_ANNOTATTION) != 0 ? "@ " : "") + ClassUtil.externalClassAccessFlags(libraryClass.u2accessFlags) + - ((libraryClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ENUM) != 0 ? "enum " : - (libraryClass.u2accessFlags & ClassConstants.INTERNAL_ACC_INTERFACE) == 0 ? "class " : + ((libraryClass.u2accessFlags & ClassConstants.ACC_ENUM) != 0 ? "enum " : + (libraryClass.u2accessFlags & ClassConstants.ACC_INTERFACE) == 0 ? "class " : "") + ClassUtil.externalClassName(libraryClass.getName()) + (libraryClass.getSuperName() == null ? "" : " extends " + @@ -214,7 +221,7 @@ implements ClassVisitor, public void visitStringConstant(Clazz clazz, StringConstant stringConstant) { println(visitorInfo(stringConstant) + " String [" + - clazz.getString(stringConstant.u2stringIndex) + "]"); + stringConstant.getString(clazz) + "]"); } @@ -275,22 +282,22 @@ implements ClassVisitor, public void visitClassConstant(Clazz clazz, ClassConstant classConstant) { println(visitorInfo(classConstant) + " Class [" + - clazz.getString(classConstant.u2nameIndex) + "]"); + classConstant.getName(clazz) + "]"); } public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) { println(visitorInfo(methodTypeConstant) + " MethodType [" + - clazz.getString(methodTypeConstant.u2descriptorIndex) + "]"); + methodTypeConstant.getType(clazz) + "]"); } public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) { println(visitorInfo(nameAndTypeConstant) + " NameAndType [" + - clazz.getString(nameAndTypeConstant.u2nameIndex) + " " + - clazz.getString(nameAndTypeConstant.u2descriptorIndex) + "]"); + nameAndTypeConstant.getName(clazz) + " " + + nameAndTypeConstant.getType(clazz) + "]"); } @@ -387,7 +394,7 @@ implements ClassVisitor, public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) { println(visitorInfo(unknownAttribute) + - " Unknown attribute (" + clazz.getString(unknownAttribute.u2attributeNameIndex) + ")"); + " Unknown attribute (" + unknownAttribute.getAttributeName(clazz) + ")"); } @@ -485,6 +492,17 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + println(visitorInfo(methodParametersAttribute) + + " Method parameters attribute (count = " + methodParametersAttribute.u1parametersCount + ")"); + + indent(); + methodParametersAttribute.parametersAccept(clazz, method, this); + outdent(); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { println(visitorInfo(exceptionsAttribute) + @@ -606,7 +624,7 @@ implements ClassVisitor, public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute) { println(visitorInfo(runtimeVisibleParameterAnnotationsAttribute) + - " Runtime visible parameter annotations attribute (parameter count = " + runtimeVisibleParameterAnnotationsAttribute.u2parametersCount + "):"); + " Runtime visible parameter annotations attribute (parameter count = " + runtimeVisibleParameterAnnotationsAttribute.u1parametersCount + "):"); indent(); runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz, method, this); @@ -617,7 +635,7 @@ implements ClassVisitor, public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute) { println(visitorInfo(runtimeInvisibleParameterAnnotationsAttribute) + - " Runtime invisible parameter annotations attribute (parameter count = " + runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount + "):"); + " Runtime invisible parameter annotations attribute (parameter count = " + runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount + "):"); indent(); runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz, method, this); @@ -625,6 +643,28 @@ implements ClassVisitor, } + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + println(visitorInfo(runtimeVisibleTypeAnnotationsAttribute) + + " Runtime visible type annotations attribute"); + + indent(); + runtimeVisibleTypeAnnotationsAttribute.typeAnnotationsAccept(clazz, this); + outdent(); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + println(visitorInfo(runtimeInvisibleTypeAnnotationsAttribute) + + " Runtime invisible type annotations attribute"); + + indent(); + runtimeInvisibleTypeAnnotationsAttribute.typeAnnotationsAccept(clazz, this); + outdent(); + } + + public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) { println(visitorInfo(annotationDefaultAttribute) + @@ -870,6 +910,16 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + println("p" + parameterIndex + ": Access flags: 0x" + Integer.toHexString(parameterInfo.u2accessFlags) + " = " + + ClassUtil.externalParameterAccessFlags(parameterInfo.u2accessFlags) + " [" + + (parameterInfo.u2nameIndex == 0 ? "" : parameterInfo.getName(clazz)) + "]"); + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -877,8 +927,8 @@ implements ClassVisitor, println("v" + localVariableInfo.u2index + ": " + localVariableInfo.u2startPC + " -> " + (localVariableInfo.u2startPC + localVariableInfo.u2length) + " [" + - clazz.getString(localVariableInfo.u2descriptorIndex) + " " + - clazz.getString(localVariableInfo.u2nameIndex) + "]"); + localVariableInfo.getDescriptor(clazz) + " " + + localVariableInfo.getName(clazz) + "]"); } @@ -889,8 +939,8 @@ implements ClassVisitor, println("v" + localVariableTypeInfo.u2index + ": " + localVariableTypeInfo.u2startPC + " -> " + (localVariableTypeInfo.u2startPC + localVariableTypeInfo.u2length) + " [" + - clazz.getString(localVariableTypeInfo.u2signatureIndex) + " " + - clazz.getString(localVariableTypeInfo.u2nameIndex) + "]"); + localVariableTypeInfo.getSignature(clazz) + " " + + localVariableTypeInfo.getName(clazz) + "]"); } @@ -899,7 +949,7 @@ implements ClassVisitor, public void visitAnnotation(Clazz clazz, Annotation annotation) { println(visitorInfo(annotation) + - " Annotation [" + clazz.getString(annotation.u2typeIndex) + "]:"); + " Annotation [" + annotation.getType(clazz) + "]:"); indent(); annotation.elementValuesAccept(clazz, this); @@ -907,6 +957,126 @@ implements ClassVisitor, } + // Implementations for TypeAnnotationVisitor. + + public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) + { + println(visitorInfo(typeAnnotation) + + " Type annotation [" + typeAnnotation.getType(clazz) + "]:"); + + indent(); + typeAnnotation.targetInfoAccept(clazz, this); + + println("Type path (count = " + typeAnnotation.typePath.length + "):"); + indent(); + typeAnnotation.typePathInfosAccept(clazz, this); + outdent(); + + typeAnnotation.elementValuesAccept(clazz, this); + + outdent(); + } + + + // Implementations for TargetInfoVisitor. + + public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo) + { + println("Target (type = 0x" + Integer.toHexString(typeParameterTargetInfo.u1targetType) + "): Parameter #" + + typeParameterTargetInfo.u1typeParameterIndex); + } + + + public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo) + { + println("Target (type = 0x" + Integer.toHexString(superTypeTargetInfo.u1targetType) + "): " + + (superTypeTargetInfo.u2superTypeIndex == 0xffff ? + "super class" : + "interface #" + superTypeTargetInfo.u2superTypeIndex)); + } + + + public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo) + { + println("Target (type = 0x" + Integer.toHexString(typeParameterBoundTargetInfo.u1targetType) + "): parameter #" + + typeParameterBoundTargetInfo.u1typeParameterIndex + ", bound #" + typeParameterBoundTargetInfo.u1boundIndex); + } + + + public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo) + { + println("Target (type = 0x" + Integer.toHexString(emptyTargetInfo.u1targetType) + ")"); + } + + + public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo) + { + println("Target (type = 0x" + Integer.toHexString(formalParameterTargetInfo.u1targetType) + "): formal parameter #" + + formalParameterTargetInfo.u1formalParameterIndex); + } + + + public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo) + { + println("Target (type = 0x" + Integer.toHexString(throwsTargetInfo.u1targetType) + "): throws #" + + throwsTargetInfo.u2throwsTypeIndex); + } + + + public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) + { + println("Target (type = 0x" + Integer.toHexString(localVariableTargetInfo.u1targetType) + "): local variables (count = " + + localVariableTargetInfo.u2tableLength + ")"); + + indent(); + localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this); + outdent(); + } + + + public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo) + { + println("Target (type = 0x" + Integer.toHexString(catchTargetInfo.u1targetType) + "): catch #" + + catchTargetInfo.u2exceptionTableIndex); + } + + + public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo) + { + println("Target (type = 0x" + Integer.toHexString(offsetTargetInfo.u1targetType) + "): offset " + + offsetTargetInfo.u2offset); + } + + + public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo) + { + println("Target (type = 0x" + Integer.toHexString(typeArgumentTargetInfo.u1targetType) + "): offset " + + typeArgumentTargetInfo.u2offset + ", type argument " + + typeArgumentTargetInfo.u1typeArgumentIndex); + } + + + // Implementations for TypePathInfoVisitor. + + public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo) + { + println("kind = " + + typePathInfo.u1typePathKind + ", argument index = " + + typePathInfo.u1typeArgumentIndex); + } + + + // Implementations for LocalVariableTargetElementVisitor. + + public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement) + { + println("v" + + localVariableTargetElement.u2index + ": " + + localVariableTargetElement.u2startPC + " -> " + + (localVariableTargetElement.u2startPC + localVariableTargetElement.u2length)); + } + + // Implementations for ElementValueVisitor. public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) @@ -914,7 +1084,7 @@ implements ClassVisitor, println(visitorInfo(constantElementValue) + " Constant element value [" + (constantElementValue.u2elementNameIndex == 0 ? "(default)" : - clazz.getString(constantElementValue.u2elementNameIndex)) + " '" + + constantElementValue.getMethodName(clazz)) + " '" + constantElementValue.u1tag + "']"); indent(); @@ -928,9 +1098,9 @@ implements ClassVisitor, println(visitorInfo(enumConstantElementValue) + " Enum constant element value [" + (enumConstantElementValue.u2elementNameIndex == 0 ? "(default)" : - clazz.getString(enumConstantElementValue.u2elementNameIndex)) + ", " + - clazz.getString(enumConstantElementValue.u2typeNameIndex) + ", " + - clazz.getString(enumConstantElementValue.u2constantNameIndex) + "]"); + enumConstantElementValue.getMethodName(clazz)) + ", " + + enumConstantElementValue.getTypeName(clazz) + ", " + + enumConstantElementValue.getConstantName(clazz) + "]"); } @@ -939,8 +1109,8 @@ implements ClassVisitor, println(visitorInfo(classElementValue) + " Class element value [" + (classElementValue.u2elementNameIndex == 0 ? "(default)" : - clazz.getString(classElementValue.u2elementNameIndex)) + ", " + - clazz.getString(classElementValue.u2classInfoIndex) + "]"); + classElementValue.getMethodName(clazz)) + ", " + + classElementValue.getClassName(clazz) + "]"); } @@ -949,7 +1119,7 @@ implements ClassVisitor, println(visitorInfo(annotationElementValue) + " Annotation element value [" + (annotationElementValue.u2elementNameIndex == 0 ? "(default)" : - clazz.getString(annotationElementValue.u2elementNameIndex)) + "]:"); + annotationElementValue.getMethodName(clazz)) + "]:"); indent(); annotationElementValue.annotationAccept(clazz, this); @@ -962,7 +1132,7 @@ implements ClassVisitor, println(visitorInfo(arrayElementValue) + " Array element value [" + (arrayElementValue.u2elementNameIndex == 0 ? "(default)" : - clazz.getString(arrayElementValue.u2elementNameIndex)) + "]:"); + arrayElementValue.getMethodName(clazz)) + "]:"); indent(); arrayElementValue.elementValuesAccept(clazz, annotation, this); diff --git a/src/proguard/classfile/visitor/ClassVersionFilter.java b/src/proguard/classfile/visitor/ClassVersionFilter.java index 73bcc6a..0b80b10 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/visitor/ClassVersionSetter.java b/src/proguard/classfile/visitor/ClassVersionSetter.java index d3f0183..3caf045 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 c423446..979b822 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 0b971f0..d82a674 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +53,8 @@ implements ClassVisitor { // Is this an abstract class or an interface? if ((programClass.getAccessFlags() & - (ClassConstants.INTERNAL_ACC_INTERFACE | - ClassConstants.INTERNAL_ACC_ABSTRACT)) != 0) + (ClassConstants.ACC_INTERFACE | + ClassConstants.ACC_ABSTRACT)) != 0) { // Travel down the hierarchy. Clazz[] subClasses = programClass.subClasses; @@ -78,8 +78,8 @@ implements ClassVisitor { // Is this an abstract class or interface? if ((libraryClass.getAccessFlags() & - (ClassConstants.INTERNAL_ACC_INTERFACE | - ClassConstants.INTERNAL_ACC_ABSTRACT)) != 0) + (ClassConstants.ACC_INTERFACE | + ClassConstants.ACC_ABSTRACT)) != 0) { // Travel down the hierarchy. Clazz[] subClasses = libraryClass.subClasses; diff --git a/src/proguard/classfile/visitor/DotClassClassVisitor.java b/src/proguard/classfile/visitor/DotClassClassVisitor.java index 979f846..5960ef6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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/DynamicReturnedClassVisitor.java b/src/proguard/classfile/visitor/DynamicReturnedClassVisitor.java new file mode 100644 index 0000000..f9ac3cb --- /dev/null +++ b/src/proguard/classfile/visitor/DynamicReturnedClassVisitor.java @@ -0,0 +1,68 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.classfile.visitor; + +import proguard.classfile.Clazz; +import proguard.classfile.constant.*; +import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.util.*; + +/** + * This ConstantVisitor lets a given ClassVisitor visit all the referenced + * classes that are returned by the invoke dynamic constants that it visits. + * + * @author Eric Lafortune + */ +public class DynamicReturnedClassVisitor +extends SimplifiedVisitor +implements ConstantVisitor +{ + protected final ClassVisitor classVisitor; + + + public DynamicReturnedClassVisitor(ClassVisitor classVisitor) + { + this.classVisitor = classVisitor; + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + { + // Is the method returning a class type? + Clazz[] referencedClasses = invokeDynamicConstant.referencedClasses; + if (referencedClasses != null && + referencedClasses.length > 0 && + ClassUtil.isInternalClassType(ClassUtil.internalMethodReturnType(invokeDynamicConstant.getType(clazz)))) + { + // Let the visitor visit the return type class, if any. + Clazz referencedClass = referencedClasses[referencedClasses.length - 1]; + if (referencedClass != null) + { + referencedClass.accept(classVisitor); + } + } + } +} diff --git a/src/proguard/classfile/visitor/ExceptClassFilter.java b/src/proguard/classfile/visitor/ExceptClassFilter.java index 25c6e68..b216ba7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 bdf72bd..acc758c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 5c476b6..a3071a6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 2fd18ae..c7b05db 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 de7139b..3a08892 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +21,9 @@ package proguard.classfile.visitor; import proguard.classfile.*; -import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.attribute.*; import proguard.classfile.attribute.visitor.ExceptionInfoVisitor; +import proguard.classfile.constant.visitor.ConstantVisitor; /** * This <code>ExceptionInfoVisitor</code> lets a given diff --git a/src/proguard/classfile/visitor/ExceptionHandlerFilter.java b/src/proguard/classfile/visitor/ExceptionHandlerFilter.java index 36ead5e..25df0ac 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 c84473a..babee27 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 626a32e..9ce10ef 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 334b85f..ac05841 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,9 +20,9 @@ */ package proguard.classfile.visitor; -import proguard.classfile.*; -import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.Clazz; import proguard.classfile.constant.ClassConstant; +import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.SimplifiedVisitor; /** diff --git a/src/proguard/classfile/visitor/ImplementedClassFilter.java b/src/proguard/classfile/visitor/ImplementedClassFilter.java index abbacfb..accbb6a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 8e7010d..ee42fe2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,9 +20,9 @@ */ package proguard.classfile.visitor; -import proguard.classfile.*; -import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.Clazz; import proguard.classfile.constant.ClassConstant; +import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.SimplifiedVisitor; /** diff --git a/src/proguard/classfile/visitor/LibraryClassFilter.java b/src/proguard/classfile/visitor/LibraryClassFilter.java index 7437ed3..894c029 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 eae0698..c58798c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 6bdc152..4041e77 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +42,9 @@ implements MemberVisitor // way if more of them are required at the same time. In that case, one // of them being set is sufficient. private static final int ACCESS_MASK = - ClassConstants.INTERNAL_ACC_PUBLIC | - ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_PROTECTED; + ClassConstants.ACC_PUBLIC | + ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_PROTECTED; private final int requiredSetAccessFlags; private final int requiredUnsetAccessFlags; diff --git a/src/proguard/classfile/visitor/MemberClassAccessFilter.java b/src/proguard/classfile/visitor/MemberClassAccessFilter.java index 3605407..40418f4 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 46665f8..d1a3d2e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 58df4a7..55df638 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 cce515a..3c0a646 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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/MemberDescriptorReferencedClassVisitor.java b/src/proguard/classfile/visitor/MemberDescriptorReferencedClassVisitor.java new file mode 100644 index 0000000..9ac1219 --- /dev/null +++ b/src/proguard/classfile/visitor/MemberDescriptorReferencedClassVisitor.java @@ -0,0 +1,65 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.classfile.visitor; + +import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.visitor.*; +import proguard.classfile.attribute.visitor.*; +import proguard.classfile.constant.*; +import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.util.SimplifiedVisitor; + +/** + * This MemberVisitor lets a given ClassVisitor visit all the classes + * referenced by the descriptors of the class members that it visits. + * + * @author Eric Lafortune + */ +public class MemberDescriptorReferencedClassVisitor +extends SimplifiedVisitor +implements MemberVisitor +{ + private final ClassVisitor classVisitor; + + + public MemberDescriptorReferencedClassVisitor(ClassVisitor classVisitor) + { + this.classVisitor = classVisitor; + } + + + // Implementations for MemberVisitor. + + public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) + { + // Let the visitor visit the classes referenced in the descriptor string. + programMember.referencedClassesAccept(classVisitor); + } + + + public void visitLibraryMember(LibraryClass programClass, LibraryMember libraryMember) + { + // Let the visitor visit the classes referenced in the descriptor string. + libraryMember.referencedClassesAccept(classVisitor); + } +} diff --git a/src/proguard/classfile/visitor/MemberNameFilter.java b/src/proguard/classfile/visitor/MemberNameFilter.java index 9996a4e..b40b208 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/visitor/MemberToClassVisitor.java b/src/proguard/classfile/visitor/MemberToClassVisitor.java index e82e52f..bb4bc03 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 7b45662..51a675c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 893a699..be951df 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 c9f942e..116b2af 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +86,8 @@ implements MemberVisitor new NamedMethodVisitor(programMethod.getName(programClass), programMethod.getDescriptor(programClass), new MemberAccessFilter(0, - ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_STATIC, + ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC, memberVisitor))); } } @@ -109,8 +109,8 @@ implements MemberVisitor new NamedMethodVisitor(libraryMethod.getName(libraryClass), libraryMethod.getDescriptor(libraryClass), new MemberAccessFilter(0, - ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_STATIC, + ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC, memberVisitor))); } } @@ -121,8 +121,8 @@ implements MemberVisitor private boolean isSpecial(Clazz clazz, Method method) { return (method.getAccessFlags() & - (ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_STATIC)) != 0 || - method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT); + (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC)) != 0 || + method.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT); } } diff --git a/src/proguard/classfile/visitor/MultiClassPoolVisitor.java b/src/proguard/classfile/visitor/MultiClassPoolVisitor.java index 0e96cf1..17a084a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 059e9b7..cb79b7d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 800d65f..67bb53e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 79e14c9..52a0c5a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 685f62d..381c97c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 c2baf19..397e16d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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/ParameterVisitor.java b/src/proguard/classfile/visitor/ParameterVisitor.java new file mode 100644 index 0000000..fc124ae --- /dev/null +++ b/src/proguard/classfile/visitor/ParameterVisitor.java @@ -0,0 +1,56 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.classfile.visitor; + +import proguard.classfile.*; + +/** + * This interface specifies the methods for a visitor of method parameters or + * field types (which can be considered parameters when storing values). The + * parameters do not include or count the 'this' parameter or the method return + * value. + * + * @author Eric Lafortune + */ +public interface ParameterVisitor +{ + /** + * Visits the given parameter. + * @param clazz the class of the method. + * @param member the field or method of the parameter. + * @param parameterIndex the index of the parameter. + * @param parameterCount the total number of parameters. + * @param parameterOffset the offset of the parameter, accounting for + * longs and doubles taking up two entries. + * @param parameterSize the total size of the parameters, accounting for + * longs and doubles taking up two entries. + * @param parameterType the parameter type. + * @param referencedClass the class contained in the parameter type, if any. + */ + public void visitParameter(Clazz clazz, + Member member, + int parameterIndex, + int parameterCount, + int parameterOffset, + int parameterSize, + String parameterType, + Clazz referencedClass); +} diff --git a/src/proguard/classfile/visitor/ProgramClassFilter.java b/src/proguard/classfile/visitor/ProgramClassFilter.java index 976658c..85f02a2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 cf187fb..d3d88f8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 e7fe855..09449bc 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +48,7 @@ implements ClassVisitor, AnnotationVisitor, ElementValueVisitor { - private final ClassVisitor classVisitor; + protected final ClassVisitor classVisitor; public ReferencedClassVisitor(ClassVisitor classVisitor) @@ -137,6 +137,13 @@ implements ClassVisitor, } + public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) + { + // Let the visitor visit the classes referenced in the method type constant. + methodTypeConstant.referencedClassesAccept(classVisitor); + } + + // Implementations for AttributeVisitor. public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} @@ -247,6 +254,13 @@ implements ClassVisitor, } + public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) + { + // Visit the contained annotation. + annotationElementValue.annotationAccept(clazz, this); + } + + public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) { // Visit the element values. diff --git a/src/proguard/classfile/visitor/ReferencedMemberVisitor.java b/src/proguard/classfile/visitor/ReferencedMemberVisitor.java index 3c59075..cb77b19 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 5087f48..2649a2f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 df630c7..073c635 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 6b6f84b..f50e498 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 32dccb7..8e80913 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 17a5522..c8e1ee3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it 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 34c39f3..fbaedec 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 127e922..f10e4be 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 474556c..f7cc902 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 InvocationUnit, // Initialize the parameters. boolean isStatic = - (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0; + (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0; // Count the number of parameters, taking into account their categories. int parameterSize = ClassUtil.internalMethodParameterSize(descriptor, isStatic); @@ -225,7 +225,7 @@ implements InvocationUnit, // Push the return value, if applicable. String returnType = ClassUtil.internalMethodReturnType(type); - if (returnType.charAt(0) != ClassConstants.INTERNAL_TYPE_VOID) + if (returnType.charAt(0) != ClassConstants.TYPE_VOID) { stack.push(getMethodReturnValue(clazz, methodrefConstant, returnType)); } @@ -250,7 +250,7 @@ implements InvocationUnit, // Push the return value, if applicable. String returnType = ClassUtil.internalMethodReturnType(type); - if (returnType.charAt(0) != ClassConstants.INTERNAL_TYPE_VOID) + if (returnType.charAt(0) != ClassConstants.TYPE_VOID) { stack.push(getMethodReturnValue(clazz, invokeDynamicConstant, returnType)); } @@ -417,9 +417,4 @@ implements InvocationUnit, returnTypeClass = referencedClasses[referencedClasses.length - 1]; } } - - -// public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) -// { -// } } diff --git a/src/proguard/evaluation/BranchUnit.java b/src/proguard/evaluation/BranchUnit.java index a381da7..e81b61d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 index 1c418c2..62cc42c 100644 --- a/src/proguard/evaluation/ClassConstantValueFactory.java +++ b/src/proguard/evaluation/ClassConstantValueFactory.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 @@ 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.*; +import proguard.classfile.constant.ClassConstant; +import proguard.evaluation.value.ValueFactory; /** * This class creates java.lang.Class ReferenceValue instances that correspond @@ -46,7 +44,7 @@ extends ConstantValueFactory 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, + value = valueFactory.createReferenceValue(ClassConstants.NAME_JAVA_LANG_CLASS, classConstant.javaLangClassClass, false); } diff --git a/src/proguard/evaluation/ConstantValueFactory.java b/src/proguard/evaluation/ConstantValueFactory.java index 0afb20c..6875bde 100644 --- a/src/proguard/evaluation/ConstantValueFactory.java +++ b/src/proguard/evaluation/ConstantValueFactory.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,14 +85,14 @@ implements ConstantVisitor public void visitStringConstant(Clazz clazz, StringConstant stringConstant) { - value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING, + value = valueFactory.createReferenceValue(ClassConstants.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, + value = valueFactory.createReferenceValue(ClassConstants.NAME_JAVA_LANG_INVOKE_METHOD_HANDLE, methodHandleConstant.javaLangInvokeMethodHandleClass, false); } @@ -106,7 +106,7 @@ implements ConstantVisitor public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) { - value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_TYPE, + value = valueFactory.createReferenceValue(ClassConstants.NAME_JAVA_LANG_INVOKE_METHOD_TYPE, methodTypeConstant.javaLangInvokeMethodTypeClass, false); } diff --git a/src/proguard/evaluation/InvocationUnit.java b/src/proguard/evaluation/InvocationUnit.java index e526b35..0750894 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 3bfc5f3..d03b853 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 @@ implements InstructionVisitor private final ValueFactory valueFactory; private final BranchUnit branchUnit; private final InvocationUnit invocationUnit; + private final boolean alwaysCast; private final ConstantValueFactory constantValueFactory; private final ClassConstantValueFactory classConstantValueFactory; @@ -51,18 +52,22 @@ implements InstructionVisitor * @param stack the local stack. * @param branchUnit the class that can affect the program counter. * @param invocationUnit the class that can access other program members. + * @param alwaysCast a flag that specifies whether downcasts or casts + * of null values should always be performed. */ public Processor(Variables variables, Stack stack, ValueFactory valueFactory, BranchUnit branchUnit, - InvocationUnit invocationUnit) + InvocationUnit invocationUnit, + boolean alwaysCast) { this.variables = variables; this.stack = stack; this.valueFactory = valueFactory; this.branchUnit = branchUnit; this.invocationUnit = invocationUnit; + this.alwaysCast = alwaysCast; constantValueFactory = new ConstantValueFactory(valueFactory); classConstantValueFactory = new ClassConstantValueFactory(valueFactory); @@ -114,70 +119,83 @@ implements InstructionVisitor case InstructionConstants.OP_BALOAD: case InstructionConstants.OP_CALOAD: case InstructionConstants.OP_SALOAD: - stack.ipop(); - stack.apop(); - stack.push(valueFactory.createIntegerValue()); + { + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + stack.push(arrayReference.integerArrayLoad(arrayIndex, valueFactory)); break; - + } case InstructionConstants.OP_LALOAD: - stack.ipop(); - stack.apop(); - stack.push(valueFactory.createLongValue()); + { + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + stack.push(arrayReference.longArrayLoad(arrayIndex, valueFactory)); break; - + } case InstructionConstants.OP_FALOAD: - stack.ipop(); - stack.apop(); - stack.push(valueFactory.createFloatValue()); + { + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + stack.push(arrayReference.floatArrayLoad(arrayIndex, valueFactory)); break; - + } case InstructionConstants.OP_DALOAD: - stack.ipop(); - stack.apop(); - stack.push(valueFactory.createDoubleValue()); + { + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + stack.push(arrayReference.doubleArrayLoad(arrayIndex, valueFactory)); break; - + } case InstructionConstants.OP_AALOAD: { IntegerValue arrayIndex = stack.ipop(); ReferenceValue arrayReference = stack.apop(); - stack.push(arrayReference.arrayLoad(arrayIndex, valueFactory)); + stack.push(arrayReference.referenceArrayLoad(arrayIndex, valueFactory)); break; } - case InstructionConstants.OP_IASTORE: case InstructionConstants.OP_BASTORE: case InstructionConstants.OP_CASTORE: case InstructionConstants.OP_SASTORE: - stack.ipop(); - stack.ipop(); - stack.apop(); + { + Value value = stack.ipop(); + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + arrayReference.arrayStore(arrayIndex, value); break; - + } case InstructionConstants.OP_LASTORE: - stack.lpop(); - stack.ipop(); - stack.apop(); + { + Value value = stack.lpop(); + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + arrayReference.arrayStore(arrayIndex, value); break; - + } case InstructionConstants.OP_FASTORE: - stack.fpop(); - stack.ipop(); - stack.apop(); + { + Value value = stack.fpop(); + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + arrayReference.arrayStore(arrayIndex, value); break; - + } case InstructionConstants.OP_DASTORE: - stack.dpop(); - stack.ipop(); - stack.apop(); + { + Value value = stack.dpop(); + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + arrayReference.arrayStore(arrayIndex, value); break; - + } case InstructionConstants.OP_AASTORE: - stack.apop(); - stack.ipop(); - stack.apop(); + { + Value value = stack.apop(); + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + arrayReference.arrayStore(arrayIndex, value); break; - + } case InstructionConstants.OP_POP: stack.pop1(); break; @@ -527,8 +545,8 @@ implements InstructionVisitor break; case InstructionConstants.OP_ARRAYLENGTH: - stack.apop(); - stack.push(valueFactory.createIntegerValue()); + ReferenceValue referenceValue = stack.apop(); + stack.push(referenceValue.arrayLength(valueFactory)); break; case InstructionConstants.OP_ATHROW: @@ -591,6 +609,7 @@ implements InstructionVisitor // TODO: Check cast. ReferenceValue castValue = stack.apop(); ReferenceValue castResultValue = + !alwaysCast && castValue.isNull() == Value.ALWAYS ? castValue : castValue.isNull() == Value.NEVER ? constantValueFactory.constantValue(clazz, constantIndex).referenceValue() : constantValueFactory.constantValue(clazz, constantIndex).referenceValue().generalize(valueFactory.createReferenceValueNull()); diff --git a/src/proguard/evaluation/Stack.java b/src/proguard/evaluation/Stack.java index c449e86..9294853 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/evaluation/TracedStack.java b/src/proguard/evaluation/TracedStack.java index 08778a1..08e30e9 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,12 +24,13 @@ import proguard.evaluation.value.Value; /** * This Stack saves additional information with stack elements, to keep track - * of their origins and destinations. + * of their origins. * <p> * The stack stores a given producer Value along with each Value it 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. + * can be set. The generalized collected Value can be retrieved, either taking + * into account dup/swap instructions as proper instructions or ignoring them. * * @author Eric Lafortune */ @@ -37,6 +38,7 @@ public class TracedStack extends Stack { private Value producerValue; private Stack producerStack; + private Stack actualProducerStack; /** @@ -46,7 +48,8 @@ public class TracedStack extends Stack { super(maxSize); - producerStack = new Stack(maxSize); + producerStack = new Stack(maxSize); + actualProducerStack = new Stack(maxSize); } @@ -57,7 +60,8 @@ public class TracedStack extends Stack { super(tracedStack); - producerStack = new Stack(tracedStack.producerStack); + producerStack = new Stack(tracedStack.producerStack); + actualProducerStack = new Stack(tracedStack.actualProducerStack); } @@ -84,14 +88,15 @@ public class TracedStack extends Stack /** - * Sets the specified producer Value on the stack, without disturbing it. + * Gets the specified actual producer Value from the stack, ignoring + * dup/swap instructions, without disturbing it. * @param index the index of the stack element, counting from the bottom * of the stack. - * @param value the producer value to set. + * @return the producer value at the specified position. */ - public void setBottomProducerValue(int index, Value value) + public Value getBottomActualProducerValue(int index) { - producerStack.setBottom(index, value); + return actualProducerStack.getBottom(index); } @@ -108,14 +113,15 @@ public class TracedStack extends Stack /** - * Sets the specified producer Value on the stack, without disturbing it. + * Gets the specified actual producer Value from the stack, ignoring + * dup/swap instructions, without disturbing it. * @param index the index of the stack element, counting from the top * of the stack. - * @param value the producer value to set. + * @return the producer value at the specified position. */ - public void setTopProducerValue(int index, Value value) + public Value getTopActualProducerValue(int index) { - producerStack.setTop(index, value); + return actualProducerStack.getTop(index); } @@ -126,6 +132,7 @@ public class TracedStack extends Stack super.reset(size); producerStack.reset(size); + actualProducerStack.reset(size); } public void copy(TracedStack other) @@ -133,13 +140,15 @@ public class TracedStack extends Stack super.copy(other); producerStack.copy(other.producerStack); + actualProducerStack.copy(other.actualProducerStack); } public boolean generalize(TracedStack other) { return super.generalize(other) | - producerStack.generalize(other.producerStack); + producerStack.generalize(other.producerStack) | + actualProducerStack.generalize(other.actualProducerStack); } public void clear() @@ -147,6 +156,7 @@ public class TracedStack extends Stack super.clear(); producerStack.clear(); + actualProducerStack.clear(); } public void removeTop(int index) @@ -154,6 +164,7 @@ public class TracedStack extends Stack super.removeTop(index); producerStack.removeTop(index); + actualProducerStack.removeTop(index); } public void push(Value value) @@ -203,85 +214,99 @@ public class TracedStack extends Stack { super.dup(); - producerPop(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup(); } public void dup_x1() { super.dup_x1(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup_x1(); } public void dup_x2() { super.dup_x2(); - producerPop(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup_x2(); } public void dup2() { super.dup2(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup2(); } public void dup2_x1() { super.dup2_x1(); - producerPop(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup2_x1(); } public void dup2_x2() { super.dup2_x2(); - producerPop(); - producerPop(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup2_x2(); } public void swap() { super.swap(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.swap(); } @@ -298,14 +323,16 @@ public class TracedStack extends Stack TracedStack other = (TracedStack)object; return super.equals(object) && - this.producerStack.equals(other.producerStack); + this.producerStack.equals(other.producerStack) && + this.actualProducerStack.equals(other.actualProducerStack); } public int hashCode() { - return super.hashCode() ^ - producerStack.hashCode(); + return super.hashCode() ^ + producerStack.hashCode() ^ + actualProducerStack.hashCode(); } @@ -315,10 +342,13 @@ public class TracedStack extends Stack for (int index = 0; index < this.size(); index++) { - Value value = this.values[index]; - Value producerValue = producerStack.getBottom(index); + Value value = this.values[index]; + Value producerValue = producerStack.getBottom(index); + Value actualProducerValue = actualProducerStack.getBottom(index); buffer = buffer.append('[') - .append(producerValue == null ? "empty:" : producerValue.toString()) + .append(producerValue == null ? "empty:" : + producerValue.equals(actualProducerValue) ? producerValue.toString() : + producerValue.toString() + actualProducerValue.toString()) .append(value == null ? "empty" : value.toString()) .append(']'); } @@ -332,11 +362,13 @@ public class TracedStack extends Stack private void producerPush() { producerStack.push(producerValue); + actualProducerStack.push(producerValue); } private void producerPop() { producerStack.pop(); + actualProducerStack.pop(); } } diff --git a/src/proguard/evaluation/TracedVariables.java b/src/proguard/evaluation/TracedVariables.java index fef54e1..23e3041 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/evaluation/Variables.java b/src/proguard/evaluation/Variables.java index 16b39e7..4b3a2a4 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ArrayReferenceValue.java b/src/proguard/evaluation/value/ArrayReferenceValue.java new file mode 100644 index 0000000..56f18ad --- /dev/null +++ b/src/proguard/evaluation/value/ArrayReferenceValue.java @@ -0,0 +1,165 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.value; + +import proguard.classfile.Clazz; + +/** + * This ReferenceValue represents a partially evaluated array. It has an array + * length and possibly array values (up to a fixed maximum number). It is not + * immutable. + * + * @author Eric Lafortune + */ +class ArrayReferenceValue extends TypedReferenceValue +{ + protected final IntegerValue arrayLength; + + + /** + * Creates a new ArrayReferenceValue. + */ + public ArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength) + { + super(type, referencedClass, false); + + this.arrayLength = arrayLength; + } + + + // Implementations for ReferenceValue. + + public IntegerValue arrayLength(ValueFactory valueFactory) + { + return arrayLength; + } + + + // Implementations of binary methods of ReferenceValue. + + public ReferenceValue generalize(ReferenceValue other) + { + return other.generalize(this); + } + + + public int equal(ReferenceValue other) + { + return other.equal(this); + } + + +// // Implementations of binary ReferenceValue methods with +// // IdentifiedReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(IdentifiedReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } + + + // Implementations of binary ReferenceValue methods with + // ArrayReferenceValue arguments. + + public ReferenceValue generalize(ArrayReferenceValue other) + { + return + this.equals(other) ? this : + this.type != null && + this.type.equals(other.type) && + this.referencedClass == other.referencedClass ? new ArrayReferenceValue(this.type, + this.referencedClass, + this.arrayLength.generalize(other.arrayLength)) : + generalize((TypedReferenceValue)other); + } + + + public int equal(ArrayReferenceValue other) + { + if (this.arrayLength.equal(other.arrayLength) == NEVER) + { + return NEVER; + } + + return equal((TypedReferenceValue)other); + } + + +// // Implementations of binary ReferenceValue methods with +// // IdentifiedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedArrayReferenceValue other) +// { +// return generalize((ArrayReferenceValue)other); +// } +// +// +// public int equal(IdentifiedArrayReferenceValue other) +// { +// return equal((ArrayReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // DetailedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(DetailedArrayReferenceValue other) +// { +// return generalize((IdentifiedArrayReferenceValue)other); +// } +// +// +// public int equal(DetailedArrayReferenceValue other) +// { +// return equal((IdentifiedArrayReferenceValue)other); +// } + + + // Implementations for Object. + + public boolean equals(Object object) + { + return this == object || + super.equals(object) && + this.arrayLength.equals(((ArrayReferenceValue)object).arrayLength); + } + + + public int hashCode() + { + return super.hashCode() ^ + arrayLength.hashCode(); + } + + + public String toString() + { + return super.toString() + '['+arrayLength+']'; + } +} diff --git a/src/proguard/evaluation/value/Category1Value.java b/src/proguard/evaluation/value/Category1Value.java index a5ebf86..777e3e3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 2be6e71..80c2183 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 abbf31c..e2cd94e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/CompositeDoubleValue.java b/src/proguard/evaluation/value/CompositeDoubleValue.java index be739ed..85b606a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 0961068..35f160f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/evaluation/value/CompositeIntegerValue.java b/src/proguard/evaluation/value/CompositeIntegerValue.java index 97caa2f..de56452 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 3b8a97f..70351c8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 eb1a350..6fd96e4 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 a491bed..81f0500 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 65fab84..bd20542 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 e74ec8d..83e1eb1 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 273b5a1..c5d83b5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 5cb9104..944e8b6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 cef2a20..7e0472f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/DetailedArrayReferenceValue.java b/src/proguard/evaluation/value/DetailedArrayReferenceValue.java new file mode 100644 index 0000000..73ca067 --- /dev/null +++ b/src/proguard/evaluation/value/DetailedArrayReferenceValue.java @@ -0,0 +1,301 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.value; + +import proguard.classfile.Clazz; +import proguard.classfile.util.ClassUtil; +import proguard.util.ArrayUtil; + +/** + * This IdentifiedArrayReferenceValue represents an identified array reference + * value with its elements. + * + * @author Eric Lafortune + */ +class DetailedArrayReferenceValue extends IdentifiedArrayReferenceValue +{ + private static final int MAXIMUM_STORED_ARRAY_LENGTH = 32; + + + private final Value[] values; + + + /** + * Creates a new array reference value with the given ID. + */ + public DetailedArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength, + ValueFactory valuefactory, + int id) + { + super(type, referencedClass, arrayLength, valuefactory, id); + + // Is the array short enough to analyze? + if (arrayLength.isParticular() && + arrayLength.value() <= MAXIMUM_STORED_ARRAY_LENGTH) + { + // Initialize the values of the array. + InitialValueFactory initialValueFactory = + new InitialValueFactory(valuefactory); + + String elementType = ClassUtil.isInternalArrayType(type) ? + type.substring(1) : + type; + + this.values = new Value[arrayLength.value()]; + + for (int index = 0; index < values.length; index++) + { + values[index] = initialValueFactory.createValue(elementType); + } + } + else + { + // Just ignore the values of the array. + this.values = null; + } + } + + + // Implementations for ReferenceValue. + + public IntegerValue integerArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + Value value = arrayLoad(indexValue, valueFactory); + return value != null ? + value.integerValue() : + super.integerArrayLoad(indexValue, valueFactory); + } + + + public LongValue longArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + Value value = arrayLoad(indexValue, valueFactory); + return value != null ? + value.longValue() : + super.longArrayLoad(indexValue, valueFactory); + } + + + public FloatValue floatArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + Value value = arrayLoad(indexValue, valueFactory); + return value != null ? + value.floatValue() : + super.floatArrayLoad(indexValue, valueFactory); + } + + + public DoubleValue doubleArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + Value value = arrayLoad(indexValue, valueFactory); + return value != null ? + value.doubleValue() : + super.doubleArrayLoad(indexValue, valueFactory); + } + + + public ReferenceValue referenceArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + Value value = arrayLoad(indexValue, valueFactory); + return value != null ? + value.referenceValue() : + super.referenceArrayLoad(indexValue, valueFactory); + } + + + /** + * Returns the specified untyped value from the given array, or null if it + * is unknown. + */ + private Value arrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + if (values != null && + indexValue.isParticular()) + { + int index = indexValue.value(); + if (index >=0 && + index < values.length) + { + return values[index]; + } + } + + return null; + } + + + public void arrayStore(IntegerValue indexValue, Value value) + { + if (values != null) + { + if (indexValue.isParticular()) + { + int index = indexValue.value(); + if (index >=0 && + index < values.length) + { + values[index] = value; + } + } + else + { + for (int index = 0; index < values.length; index++) + { + values[index].generalize(value); + } + } + } + } + + + // Implementations of binary methods of ReferenceValue. + + public ReferenceValue generalize(ReferenceValue other) + { + return other.generalize(this); + } + + + public int equal(ReferenceValue other) + { + return other.equal(this); + } + + +// // Implementations of binary ReferenceValue methods with +// // IdentifiedReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(IdentifiedReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // ArrayReferenceValue arguments. +// +// public ReferenceValue generalize(ArrayReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(ArrayReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // IdentifiedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedArrayReferenceValue other) +// { +// return generalize((ArrayReferenceValue)other); +// } +// +// +// public int equal(IdentifiedArrayReferenceValue other) +// { +// return equal((ArrayReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // DetailedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(DetailedArrayReferenceValue other) +// { +// return generalize((IdentifiedArrayReferenceValue)other); +// } +// +// +// public int equal(DetailedArrayReferenceValue other) +// { +// return equal((IdentifiedArrayReferenceValue)other); +// } + + + // Implementations for Value. + + public boolean isParticular() + { + if (values == null) + { + return false; + } + + for (int index = 0; index < values.length; index++) + { + if (!values[index].isParticular()) + { + return false; + } + } + + return true; + } + + + // Implementations for Object. + + public boolean equals(Object object) + { + return this == object || + super.equals(object) && + ArrayUtil.equalOrNull(this.values, ((DetailedArrayReferenceValue)object).values); + } + + + public int hashCode() + { + return super.hashCode() ^ + ArrayUtil.hashCodeOrNull(values); + } + + + public String toString() + { + if (values == null) + { + return super.toString(); + } + + StringBuffer buffer = new StringBuffer(super.toString()); + + buffer.append('{'); + for (int index = 0; index < values.length; index++) + { + buffer.append(values[index]); + buffer.append(index < values.length-1 ? ',' : '}'); + } + + return buffer.toString(); + } +}
\ No newline at end of file diff --git a/src/proguard/evaluation/value/DetailedValueFactory.java b/src/proguard/evaluation/value/DetailedValueFactory.java new file mode 100644 index 0000000..d28b8ab --- /dev/null +++ b/src/proguard/evaluation/value/DetailedValueFactory.java @@ -0,0 +1,48 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.value; + +import proguard.classfile.*; + +/** + * This identified value factory creates array reference values that also + * represent their elements, in as far as possible. + * + * @author Eric Lafortune + */ +public class DetailedValueFactory +extends IdentifiedValueFactory +{ + // Implementations for ReferenceValue. + + public ReferenceValue createArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength) + { + return type == null ? + REFERENCE_VALUE_NULL : + new DetailedArrayReferenceValue(ClassConstants.TYPE_ARRAY + type, + referencedClass, + arrayLength, + this, + referenceID++); + } +}
\ No newline at end of file diff --git a/src/proguard/evaluation/value/DoubleValue.java b/src/proguard/evaluation/value/DoubleValue.java index 6630b2f..7587ed3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -354,6 +354,6 @@ public abstract class DoubleValue extends Category2Value public final String internalType() { - return String.valueOf(ClassConstants.INTERNAL_TYPE_DOUBLE); + return String.valueOf(ClassConstants.TYPE_DOUBLE); } } diff --git a/src/proguard/evaluation/value/FloatValue.java b/src/proguard/evaluation/value/FloatValue.java index 6dc8bee..ce7806e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -354,6 +354,6 @@ public abstract class FloatValue extends Category1Value public final String internalType() { - return String.valueOf(ClassConstants.INTERNAL_TYPE_FLOAT); + return String.valueOf(ClassConstants.TYPE_FLOAT); } } diff --git a/src/proguard/evaluation/value/IdentifiedArrayReferenceValue.java b/src/proguard/evaluation/value/IdentifiedArrayReferenceValue.java new file mode 100644 index 0000000..3b597a1 --- /dev/null +++ b/src/proguard/evaluation/value/IdentifiedArrayReferenceValue.java @@ -0,0 +1,159 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.value; + +import proguard.classfile.Clazz; + +/** + * This ArrayReferenceValue represents an array reference value that is + * identified by a unique ID. + * + * @author Eric Lafortune + */ +class IdentifiedArrayReferenceValue extends ArrayReferenceValue +{ + private final ValueFactory valuefactory; + private final int id; + + + /** + * Creates a new array reference value with the given ID. + */ + public IdentifiedArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength, + ValueFactory valuefactory, + int id) + { + super(type, referencedClass, arrayLength); + + this.valuefactory = valuefactory; + this.id = id; + } + + + // Implementations of binary methods of ReferenceValue. + + public ReferenceValue generalize(ReferenceValue other) + { + return other.generalize(this); + } + + + public int equal(ReferenceValue other) + { + return other.equal(this); + } + + +// // Implementations of binary ReferenceValue methods with +// // IdentifiedReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(IdentifiedReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // ArrayReferenceValue arguments. +// +// public ReferenceValue generalize(ArrayReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(ArrayReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } +// +// + // Implementations of binary ReferenceValue methods with + // IdentifiedArrayReferenceValue arguments. + +// public ReferenceValue generalize(IdentifiedArrayReferenceValue other) +// { +// return generalize((ArrayReferenceValue)other); +// } + + + public int equal(IdentifiedArrayReferenceValue other) + { + return this.equals(other) ? ALWAYS : + this.equal((TypedReferenceValue)other); + } + + +// // Implementations of binary ReferenceValue methods with +// // DetailedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(DetailedArrayReferenceValue other) +// { +// return generalize((IdentifiedArrayReferenceValue)other); +// } +// +// +// public int equal(DetailedArrayReferenceValue other) +// { +// return equal((IdentifiedArrayReferenceValue)other); +// } + + + // Implementations for Value. + + public boolean isSpecific() + { + return true; + } + + + // Implementations for Object. + + public boolean equals(Object object) + { + return this == object || + super.equals(object) && + this.valuefactory.equals(((IdentifiedArrayReferenceValue)object).valuefactory) && + this.id == ((IdentifiedArrayReferenceValue)object).id; + } + + + public int hashCode() + { + return super.hashCode() ^ + valuefactory.hashCode() ^ + id; + } + + + public String toString() + { + return super.toString() + '#' + id; + } +}
\ No newline at end of file diff --git a/src/proguard/evaluation/value/IdentifiedDoubleValue.java b/src/proguard/evaluation/value/IdentifiedDoubleValue.java index 4ff2466..6740a2c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 c8349bc..62e4b2b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 6c3ee5d..ac1d033 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 e0b68f2..b670ae6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 5cfbd60..7f0196b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,18 +23,19 @@ package proguard.evaluation.value; import proguard.classfile.Clazz; /** - * This LongValue represents a reference value that is identified by a unique ID. + * This TypedReferenceValue represents a reference value that is identified by a + * unique ID. * * @author Eric Lafortune */ -final class IdentifiedReferenceValue extends ReferenceValue +class IdentifiedReferenceValue extends TypedReferenceValue { private final ValueFactory valuefactory; private final int id; /** - * Creates a new long value with the given ID. + * Creates a new reference value with the given ID. */ public IdentifiedReferenceValue(String type, Clazz referencedClass, @@ -49,25 +50,81 @@ final class IdentifiedReferenceValue extends ReferenceValue } - // Implementations for ReferenceValue. + // Implementations of binary methods of ReferenceValue. + + public ReferenceValue generalize(ReferenceValue other) + { + return other.generalize(this); + } + public int equal(ReferenceValue other) { - return this.equals(other) ? ALWAYS : MAYBE; + return other.equal(this); } - // Implementations of binary methods of ReferenceValue. + // Implementations of binary ReferenceValue methods with + // IdentifiedReferenceValue arguments. - public ReferenceValue generalize(ReferenceValue other) +// public ReferenceValue generalize(IdentifiedReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } + + + public int equal(IdentifiedReferenceValue 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); + return this.equals(other) ? ALWAYS : + this.equal((TypedReferenceValue)other); } +// // Implementations of binary ReferenceValue methods with +// // ArrayReferenceValue arguments. +// +// public ReferenceValue generalize(ArrayReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(ArrayReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // IdentifiedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedArrayReferenceValue other) +// { +// return generalize((ArrayReferenceValue)other); +// } +// +// +// public int equal(IdentifiedArrayReferenceValue other) +// { +// return equal((ArrayReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // DetailedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(DetailedArrayReferenceValue other) +// { +// return generalize((IdentifiedArrayReferenceValue)other); +// } +// +// +// public int equal(DetailedArrayReferenceValue other) +// { +// return equal((IdentifiedArrayReferenceValue)other); +// } + + // Implementations for Value. public boolean isSpecific() diff --git a/src/proguard/evaluation/value/IdentifiedValueFactory.java b/src/proguard/evaluation/value/IdentifiedValueFactory.java index be5c885..6bd1d5d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,21 +21,20 @@ package proguard.evaluation.value; import proguard.classfile.*; -import proguard.classfile.util.ClassUtil; /** - * This class provides methods to create and reuse IntegerValue objects. + * This particular value factory attaches a unique ID to any unknown values. * * @author Eric Lafortune */ public class IdentifiedValueFactory -extends SpecificValueFactory +extends ParticularValueFactory { - private int integerID; - private int longID; - private int floatID; - private int doubleID; - private int referenceID; + protected int integerID; + protected int longID; + protected int floatID; + protected int doubleID; + protected int referenceID; // Implementations for ValueFactory. @@ -70,6 +69,24 @@ extends SpecificValueFactory { return type == null ? REFERENCE_VALUE_NULL : - new IdentifiedReferenceValue(type, referencedClass, mayBeNull, this, referenceID++); + new IdentifiedReferenceValue(type, + referencedClass, + mayBeNull, + this, + referenceID++); + } + + + public ReferenceValue createArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength) + { + return type == null ? + REFERENCE_VALUE_NULL : + new IdentifiedArrayReferenceValue(ClassConstants.TYPE_ARRAY + type, + referencedClass, + arrayLength, + this, + referenceID++); } }
\ No newline at end of file diff --git a/src/proguard/evaluation/value/InitialValueFactory.java b/src/proguard/evaluation/value/InitialValueFactory.java new file mode 100644 index 0000000..4b2cf29 --- /dev/null +++ b/src/proguard/evaluation/value/InitialValueFactory.java @@ -0,0 +1,79 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.value; + +import proguard.classfile.ClassConstants; + +/** + * This value factory creates initial values for fields and array elements, + * with the help of a given value factory. Note that this class itself doesn't + * implement ValueFactory. + * + * @author Eric Lafortune + */ +public class InitialValueFactory +{ + private final ValueFactory valueFactory; + + + /** + * Creates a new InitialValueFactory. + * @param valueFactory the value factory that will actually create the + * values. + */ + public InitialValueFactory(ValueFactory valueFactory) + { + this.valueFactory = valueFactory; + } + + + /** + * Creates an initial value (0, 0L, 0.0f, 0.0, null) of the given type. + */ + public Value createValue(String type) + { + switch (type.charAt(0)) + { + case ClassConstants.TYPE_BOOLEAN: + case ClassConstants.TYPE_BYTE: + case ClassConstants.TYPE_CHAR: + case ClassConstants.TYPE_SHORT: + case ClassConstants.TYPE_INT: + return valueFactory.createIntegerValue(0); + + case ClassConstants.TYPE_LONG: + return valueFactory.createLongValue(0L); + + case ClassConstants.TYPE_FLOAT: + return valueFactory.createFloatValue(0.0f); + + case ClassConstants.TYPE_DOUBLE: + return valueFactory.createDoubleValue(0.0); + + case ClassConstants.TYPE_CLASS_START: + case ClassConstants.TYPE_ARRAY: + return valueFactory.createReferenceValueNull(); + + default: + throw new IllegalArgumentException("Invalid type ["+type+"]"); + } + } +} diff --git a/src/proguard/evaluation/value/InstructionOffsetValue.java b/src/proguard/evaluation/value/InstructionOffsetValue.java index 07a44ee..7cb953e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -143,60 +143,73 @@ public class InstructionOffsetValue extends Category1Value */ public final Value generalize(InstructionOffsetValue other) { - // If the values array of either is null, return the other one. - if (this.values == null) + // If the values array of either is null, we can return the other one. + int[] thisValues = this.values; + if (thisValues == null) { return other; } - if (other.values == null) + int[] otherValues = other.values; + if (otherValues == null) { return this; } // Compute the length of the union of the arrays. - int newLength = this.values.length; - for (int index = 0; index < other.values.length; index++) + int newLength = thisValues.length; + for (int index = 0; index < otherValues.length; index++) { - if (!this.contains(other.values[index])) + if (!this.contains(otherValues[index])) { newLength++; } } - // If the length of the union array is equal to the length of the values - // array of either, return it. - if (newLength == other.values.length) + // If the length of the union array is equal to the length of the other + // values array, we can return it. + if (newLength == otherValues.length) { return other; } - // The ordering of the this array may not be right, so we can't just - // use it. - //if (newLength == this.values.length) - //{ - // return this; - //} + // If the length of the union array is equal to the length of this + // values array, we can return it. We have to make sure that the other + // values are at the end. We'll just test one special case, with a + // single other value. + if (newLength == this.values.length && + otherValues.length == 1 && + thisValues[thisValues.length-1] == otherValues[0]) + { + return this; + } // Create the union array. + int newIndex = 0; int[] newValues = new int[newLength]; - int newIndex = 0; + // Is the length of the union array is equal to the sum of the lengths? + if (newLength == thisValues.length + otherValues.length) + { + // We can just copy all values, because they are unique. + System.arraycopy(thisValues, 0, newValues, 0, thisValues.length); - // Copy the values that are different from the other array. - for (int index = 0; index < this.values.length; index++) + newIndex = thisValues.length; + } + else { - if (!other.contains(this.values[index])) + // Copy the values that are different from the other array. + for (int index = 0; index < thisValues.length; index++) { - newValues[newIndex++] = this.values[index]; + if (!other.contains(thisValues[index])) + { + newValues[newIndex++] = thisValues[index]; + } } } // Copy the values from the other array. - for (int index = 0; index < other.values.length; index++) - { - newValues[newIndex++] = other.values[index]; - } + System.arraycopy(otherValues, 0, newValues, newIndex, otherValues.length); return new InstructionOffsetValue(newValues); } @@ -231,7 +244,7 @@ public class InstructionOffsetValue extends Category1Value public final String internalType() { - return String.valueOf(ClassConstants.INTERNAL_TYPE_INT); + return String.valueOf(ClassConstants.TYPE_INT); } diff --git a/src/proguard/evaluation/value/IntegerValue.java b/src/proguard/evaluation/value/IntegerValue.java index b1824c6..148c0ea 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -997,6 +997,6 @@ public abstract class IntegerValue extends Category1Value public final String internalType() { - return String.valueOf(ClassConstants.INTERNAL_TYPE_INT); + return String.valueOf(ClassConstants.TYPE_INT); } } diff --git a/src/proguard/evaluation/value/LongValue.java b/src/proguard/evaluation/value/LongValue.java index e23c13c..e8f9e12 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -549,6 +549,6 @@ public abstract class LongValue extends Category2Value public final String internalType() { - return String.valueOf(ClassConstants.INTERNAL_TYPE_INT); + return String.valueOf(ClassConstants.TYPE_INT); } } diff --git a/src/proguard/evaluation/value/NegatedDoubleValue.java b/src/proguard/evaluation/value/NegatedDoubleValue.java index 7619be7..25de608 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 51b5074..7a05579 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 1729083..cbbabdd 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 7510524..bb9f729 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 e8c5aa7..d97eb5f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +182,9 @@ final class ParticularDoubleValue extends SpecificDoubleValue public IntegerValue compare(ParticularDoubleValue other) { - return this.value < other.value ? SpecificValueFactory.INTEGER_VALUE_M1 : - this.value == other.value ? SpecificValueFactory.INTEGER_VALUE_0 : - SpecificValueFactory.INTEGER_VALUE_1; + return this.value < other.value ? ParticularValueFactory.INTEGER_VALUE_M1 : + this.value == other.value ? ParticularValueFactory.INTEGER_VALUE_0 : + ParticularValueFactory.INTEGER_VALUE_1; } diff --git a/src/proguard/evaluation/value/ParticularFloatValue.java b/src/proguard/evaluation/value/ParticularFloatValue.java index cbdde31..9084b36 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +182,9 @@ final class ParticularFloatValue extends SpecificFloatValue public IntegerValue compare(ParticularFloatValue other) { - return this.value < other.value ? SpecificValueFactory.INTEGER_VALUE_M1 : - this.value == other.value ? SpecificValueFactory.INTEGER_VALUE_0 : - SpecificValueFactory.INTEGER_VALUE_1; + return this.value < other.value ? ParticularValueFactory.INTEGER_VALUE_M1 : + this.value == other.value ? ParticularValueFactory.INTEGER_VALUE_0 : + ParticularValueFactory.INTEGER_VALUE_1; } diff --git a/src/proguard/evaluation/value/ParticularIntegerValue.java b/src/proguard/evaluation/value/ParticularIntegerValue.java index 609e95f..86f8a22 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 1903235..7e7cc20 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/ParticularValueFactory.java index f761938..f28c10e 100644 --- a/src/proguard/evaluation/value/SpecificValueFactory.java +++ b/src/proguard/evaluation/value/ParticularValueFactory.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,12 +20,14 @@ */ package proguard.evaluation.value; +import proguard.classfile.*; + /** - * This class provides methods to create and reuse IntegerValue objects. + * This value factory creates particular values. * * @author Eric Lafortune */ -public class SpecificValueFactory +public class ParticularValueFactory extends ValueFactory { // Shared copies of Value objects, to avoid creating a lot of objects. @@ -69,9 +71,9 @@ extends ValueFactory public LongValue createLongValue(long value) { - return value == 0 ? LONG_VALUE_0 : - value == 1 ? LONG_VALUE_1 : - new ParticularLongValue(value); + return value == 0L ? LONG_VALUE_0 : + value == 1L ? LONG_VALUE_1 : + new ParticularLongValue(value); } @@ -94,4 +96,16 @@ extends ValueFactory value == 1.0 ? DOUBLE_VALUE_1 : new ParticularDoubleValue(value); } + + + public ReferenceValue createArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength) + { + return type == null ? + REFERENCE_VALUE_NULL : + new ArrayReferenceValue(ClassConstants.TYPE_ARRAY + type, + referencedClass, + arrayLength); + } } diff --git a/src/proguard/evaluation/value/ReferenceValue.java b/src/proguard/evaluation/value/ReferenceValue.java index 4a52e82..1f87382 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,191 +20,110 @@ */ package proguard.evaluation.value; -import proguard.classfile.*; -import proguard.classfile.util.ClassUtil; -import proguard.classfile.visitor.ClassCollector; - -import java.util.*; +import proguard.classfile.Clazz; /** - * This class represents a partially evaluated reference value. It has a type - * and a flag that indicates whether the value could be <code>null</code>. If - * the type is <code>null</code>, the value is <code>null</code>. + * This class represents a partially evaluated reference value. * * @author Eric Lafortune */ -public class ReferenceValue extends Category1Value +public abstract class ReferenceValue extends Category1Value { - private static final boolean DEBUG = false; + /** + * Returns the type. + */ + public abstract String getType(); +; + /** + * Returns the class that is referenced by the type. + */ + public abstract Clazz getReferencedClass(); - protected final String type; - protected final Clazz referencedClass; - protected final boolean mayBeNull; + // Basic unary methods. /** - * Creates a new ReferenceValue. + * Returns whether the type is <code>null</code>. */ - public ReferenceValue(String type, - Clazz referencedClass, - boolean mayBeNull) - { - this.type = type; - this.referencedClass = referencedClass; - this.mayBeNull = mayBeNull; - } + public abstract int isNull(); /** - * Returns the type. + * Returns whether the type is an instance of the given type. + */ + public abstract int instanceOf(String otherType, Clazz otherReferencedClass); + + + /** + * Returns a generalization of this ReferenceValue that may be null, + * depending on the flag. + */ + public abstract ReferenceValue generalizeMayBeNull(boolean mayBeNull); + + + /** + * Returns the length of the array, assuming this type is an array. */ - public String getType() + public IntegerValue arrayLength(ValueFactory valueFactory) { - return type; + return valueFactory.createIntegerValue(); } /** - * Returns the class that is referenced by the type. + * Returns the value of the array at the given index, assuming this type + * is an integer array. */ - public Clazz getReferencedClass() + public IntegerValue integerArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) { - return referencedClass; + return valueFactory.createIntegerValue(); } - // Basic unary methods. - /** - * Returns whether the type is <code>null</code>. + * Returns the value of the array at the given index, assuming this type + * is an long array. */ - public int isNull() + public LongValue longArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) { - return type == null ? ALWAYS : - mayBeNull ? MAYBE : - NEVER; + return valueFactory.createLongValue(); } /** - * Returns whether the type is an instance of the given type. + * Returns the value of the array at the given index, assuming this type + * is an float array. */ - public int instanceOf(String otherType, Clazz otherReferencedClass) + public FloatValue floatArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) { - String thisType = this.type; - - // If this type is null, it is never an instance of any class. - if (thisType == null) - { - return NEVER; - } - - // Start taking into account the type dimensions. - int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType); - int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType); - int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount); - - // Strip any common array prefixes. - thisType = thisType.substring(commonDimensionCount); - otherType = otherType.substring(commonDimensionCount); - - // If either stripped type is a primitive type, we can tell right away. - if (commonDimensionCount > 0 && - (ClassUtil.isInternalPrimitiveType(thisType.charAt(0)) || - ClassUtil.isInternalPrimitiveType(otherType.charAt(0)))) - { - return !thisType.equals(otherType) ? NEVER : - mayBeNull ? MAYBE : - ALWAYS; - } - - // Strip the class type prefix and suffix of this type, if any. - if (thisDimensionCount == commonDimensionCount) - { - thisType = ClassUtil.internalClassNameFromClassType(thisType); - } - - // Strip the class type prefix and suffix of the other type, if any. - if (otherDimensionCount == commonDimensionCount) - { - otherType = ClassUtil.internalClassNameFromClassType(otherType); - } - - // If this type is an array type, and the other type is not - // java.lang.Object, java.lang.Cloneable, or java.io.Serializable, - // this type can never be an instance. - if (thisDimensionCount > otherDimensionCount && - !ClassUtil.isInternalArrayInterfaceName(otherType)) - { - return NEVER; - } - - // If the other type is an array type, and this type is not - // java.lang.Object, java.lang.Cloneable, or java.io.Serializable, - // this type can never be an instance. - if (thisDimensionCount < otherDimensionCount && - !ClassUtil.isInternalArrayInterfaceName(thisType)) - { - return NEVER; - } - - // If this type may be null, it might not be an instance of any class. - if (mayBeNull) - { - return MAYBE; - } - - // If this type is equal to the other type, or if the other type is - // java.lang.Object, this type is always an instance. - if (thisType.equals(otherType) || - ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT.equals(otherType)) - { - return ALWAYS; - } - - // If this type is an array type, it's ok. - if (thisDimensionCount > otherDimensionCount) - { - return ALWAYS; - } - - // If the other type is an array type, it might be ok. - if (thisDimensionCount < otherDimensionCount) - { - return MAYBE; - } - - // If the value extends the type, we're sure. - return referencedClass != null && - otherReferencedClass != null && - referencedClass.extendsOrImplements(otherReferencedClass) ? - ALWAYS : - MAYBE; + return valueFactory.createFloatValue(); } /** - * Returns the length of the array, assuming this type is an array. + * Returns the value of the array at the given index, assuming this type + * is an double array. */ - public IntegerValue arrayLength(ValueFactory valueFactory) + public DoubleValue doubleArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) { - return valueFactory.createIntegerValue(); + return valueFactory.createDoubleValue(); } /** * Returns the value of the array at the given index, assuming this type - * is an array. + * is a reference array. + */ + public abstract ReferenceValue referenceArrayLoad(IntegerValue indexValue, ValueFactory valueFactory); + + + /** + * Stores the given value at the given index in the given array, assuming + * this type is an array. */ - public Value arrayLoad(IntegerValue integerValue, ValueFactory valueFactory) + public void arrayStore(IntegerValue indexValue, Value value) { - return - type == null ? ValueFactory.REFERENCE_VALUE_NULL : - !ClassUtil.isInternalArrayType(type) ? ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : - valueFactory.createValue(type.substring(1), - referencedClass, - true); } @@ -214,327 +133,173 @@ public class ReferenceValue extends Category1Value * Returns the generalization of this ReferenceValue and the given other * ReferenceValue. */ - public ReferenceValue generalize(ReferenceValue other) + public abstract ReferenceValue generalize(ReferenceValue other); + + + /** + * Returns whether this ReferenceValue is equal to the given other + * ReferenceValue. + * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. + */ + public abstract int equal(ReferenceValue other); + + + // Derived unary methods. + + /** + * Returns whether this ReferenceValue is not <code>null</code>. + * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. + */ + public final int isNotNull() { - // If both types are identical, the generalization is the same too. - if (this.equals(other)) - { - return this; - } - - String thisType = this.type; - String otherType = other.type; - - // If both types are nul, the generalization is null too. - if (thisType == null && otherType == null) - { - return ValueFactory.REFERENCE_VALUE_NULL; - } - - // If this type is null, the generalization is the other type, maybe null. - if (thisType == null) - { - return other.generalizeMayBeNull(true); - } - - // If the other type is null, the generalization is this type, maybe null. - if (otherType == null) - { - return this.generalizeMayBeNull(true); - } - - boolean mayBeNull = this.mayBeNull || other.mayBeNull; - - // If the two types are equal, the generalization remains the same, maybe null. - if (thisType.equals(otherType)) - { - return this.generalizeMayBeNull(mayBeNull); - } - - // Start taking into account the type dimensions. - int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType); - int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType); - int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount); - - if (thisDimensionCount == otherDimensionCount) - { - // See if we can take into account the referenced classes. - Clazz thisReferencedClass = this.referencedClass; - Clazz otherReferencedClass = other.referencedClass; - - if (thisReferencedClass != null && - otherReferencedClass != null) - { - if (thisReferencedClass.extendsOrImplements(otherReferencedClass)) - { - return other.generalizeMayBeNull(mayBeNull); - } - - if (otherReferencedClass.extendsOrImplements(thisReferencedClass)) - { - return this.generalizeMayBeNull(mayBeNull); - } - - // Collect the superclasses and interfaces of this class. - Set thisSuperClasses = new HashSet(); - 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()+"]"); - System.out.println(" This super classes: "+thisSuperClasses); - System.out.println(" Other super classes: "+otherSuperClasses); - } - - // Find the common superclasses. - thisSuperClasses.retainAll(otherSuperClasses); - - if (DEBUG) - { - System.out.println(" Common super classes: "+thisSuperClasses); - } - - // Find a class that is a subclass of all common superclasses, - // or that at least has the maximum number of common superclasses. - Clazz commonClass = null; - - int maximumSuperClassCount = -1; - - // Go over all common superclasses to find it. In case of - // multiple subclasses, keep the lowest one alphabetically, - // in order to ensure that the choice is deterministic. - Iterator commonSuperClasses = thisSuperClasses.iterator(); - while (commonSuperClasses.hasNext()) - { - Clazz commonSuperClass = (Clazz)commonSuperClasses.next(); - - int superClassCount = superClassCount(commonSuperClass, thisSuperClasses); - if (maximumSuperClassCount < superClassCount || - (maximumSuperClassCount == superClassCount && - commonClass != null && - commonClass.getName().compareTo(commonSuperClass.getName()) > 0)) - { - commonClass = commonSuperClass; - maximumSuperClassCount = superClassCount; - } - } - - if (commonClass == null) - { - 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: ["+commonClass.getName()+"]"); - } - - // TODO: Handle more difficult cases, with multiple global subclasses. - - return new ReferenceValue(commonDimensionCount == 0 ? - commonClass.getName() : - ClassUtil.internalArrayTypeFromClassName(commonClass.getName(), - commonDimensionCount), - commonClass, - mayBeNull); - } - } - else if (thisDimensionCount > otherDimensionCount) - { - // See if the other type is an interface type of arrays. - if (ClassUtil.isInternalArrayInterfaceName(ClassUtil.internalClassNameFromClassType(otherType))) - { - return other.generalizeMayBeNull(mayBeNull); - } - } - else if (thisDimensionCount < otherDimensionCount) - { - // See if this type is an interface type of arrays. - if (ClassUtil.isInternalArrayInterfaceName(ClassUtil.internalClassNameFromClassType(thisType))) - { - return this.generalizeMayBeNull(mayBeNull); - } - } - - // Reduce the common dimension count if either type is an array of - // primitives type of this dimension. - if (commonDimensionCount > 0 && - (ClassUtil.isInternalPrimitiveType(otherType.charAt(commonDimensionCount))) || - ClassUtil.isInternalPrimitiveType(thisType.charAt(commonDimensionCount))) - { - commonDimensionCount--; - } - - // Fall back on a basic Object or array of Objects type. - return commonDimensionCount == 0 ? - mayBeNull ? - ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : - ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL : - new ReferenceValue(ClassUtil.internalArrayTypeFromClassName(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT, - commonDimensionCount), - null, - mayBeNull); + return -isNull(); } + // Derived binary methods. + /** - * Returns if the number of superclasses of the given class in the given - * set of classes. + * Returns whether this ReferenceValue and the given ReferenceValue are different. + * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. */ - private int superClassCount(Clazz subClass, Set classes) + public final int notEqual(ReferenceValue other) { - int count = 0; + return -equal(other); + } - Iterator iterator = classes.iterator(); - while (iterator.hasNext()) - { - Clazz clazz = (Clazz)iterator.next(); - if (subClass.extendsOrImplements(clazz)) - { - count++; - } - } + // Similar binary methods, but this time with typed reference arguments. - return count; + /** + * Returns the generalization of this ReferenceValue and the given other + * TypedReferenceValue. + */ + public ReferenceValue generalize(TypedReferenceValue other) + { + return generalize((ReferenceValue)other); } /** * Returns whether this ReferenceValue is equal to the given other - * ReferenceValue. + * TypedReferenceValue. * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. */ - public int equal(ReferenceValue other) + public int equal(TypedReferenceValue other) { - return this.type == null && other.type == null ? ALWAYS : MAYBE; + return equal((ReferenceValue)other); } - // Derived unary methods. + // Similar binary methods, but this time with identified reference + // arguments. /** - * Returns whether this ReferenceValue is not <code>null</code>. + * Returns the generalization of this ReferenceValue and the given other + * IdentifiedReferenceValue. + */ + public ReferenceValue generalize(IdentifiedReferenceValue other) + { + return generalize((TypedReferenceValue)other); + } + + + /** + * Returns whether this ReferenceValue is equal to the given other + * IdentifiedReferenceValue. * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. */ - public final int isNotNull() + public int equal(IdentifiedReferenceValue other) { - return -isNull(); + return equal((TypedReferenceValue)other); } + // Similar binary methods, but this time with array reference arguments. + /** * Returns the generalization of this ReferenceValue and the given other - * ReferenceValue. + * ArrayReferenceValue. */ - private ReferenceValue generalizeMayBeNull(boolean mayBeNull) + public ReferenceValue generalize(ArrayReferenceValue other) { - return this.mayBeNull || !mayBeNull ? - this : - new ReferenceValue(this.type, this.referencedClass, true); + return generalize((TypedReferenceValue)other); } - // Derived binary methods. - /** - * Returns whether this ReferenceValue and the given ReferenceValue are different. + * Returns whether this ReferenceValue is equal to the given other + * ArrayReferenceValue. * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. */ - public final int notEqual(ReferenceValue other) + public int equal(ArrayReferenceValue other) { - return -equal(other); + return equal((TypedReferenceValue)other); } - // Implementations for Value. + // Similar binary methods, but this time with identified array reference + // arguments. - public final ReferenceValue referenceValue() + /** + * Returns the generalization of this ReferenceValue and the given other + * IdentifiedArrayReferenceValue. + */ + public ReferenceValue generalize(IdentifiedArrayReferenceValue other) { - return this; + return generalize((ArrayReferenceValue)other); } - public final Value generalize(Value other) - { - return this.generalize(other.referenceValue()); - } - public boolean isParticular() + /** + * Returns whether this ReferenceValue is equal to the given other + * IdentifiedArrayReferenceValue. + * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. + */ + public int equal(IdentifiedArrayReferenceValue other) { - return type == null; + return equal((ArrayReferenceValue)other); } - public final int computationalType() + + // Similar binary methods, but this time with detailed array reference + // arguments. + + /** + * Returns the generalization of this ReferenceValue and the given other + * DetailedArrayReferenceValue. + */ + public ReferenceValue generalize(DetailedArrayReferenceValue other) { - return TYPE_REFERENCE; + return generalize((IdentifiedArrayReferenceValue)other); } - public final String internalType() + + /** + * Returns whether this ReferenceValue is equal to the given other + * DetailedArrayReferenceValue. + * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. + */ + public int equal(DetailedArrayReferenceValue other) { - return - type == null ? ClassConstants.INTERNAL_TYPE_JAVA_LANG_OBJECT : - ClassUtil.isInternalArrayType(type) ? type : - ClassConstants.INTERNAL_TYPE_CLASS_START + - type + - ClassConstants.INTERNAL_TYPE_CLASS_END; + return equal((IdentifiedArrayReferenceValue)other); } - // Implementations for Object. + // Implementations for Value. - public boolean equals(Object object) + public final ReferenceValue referenceValue() { - if (this == object) - { - return true; - } - - if (object == null || - this.getClass() != object.getClass()) - { - return false; - } - - ReferenceValue other = (ReferenceValue)object; - return this.type == null ? other.type == null : - (this.mayBeNull == other.mayBeNull && - this.type.equals(other.type)); + return this; } - - public int hashCode() + public final Value generalize(Value other) { - return this.getClass().hashCode() ^ - (type == null ? 0 : type.hashCode() ^ (mayBeNull ? 0 : 1)); + return this.generalize(other.referenceValue()); } - - public String toString() + public final int computationalType() { - return type == null ? - "null" : - type + (referencedClass == null ? "?" : "") + (mayBeNull ? "" : "!"); + return TYPE_REFERENCE; } } diff --git a/src/proguard/evaluation/value/SpecificDoubleValue.java b/src/proguard/evaluation/value/SpecificDoubleValue.java index 644f553..5ee2db2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -157,7 +157,7 @@ abstract class SpecificDoubleValue extends DoubleValue // Not handling NaN properly. //return this.equals(other) ? - // SpecificValueFactory.INTEGER_VALUE_0 : + // ParticularValueFactory.INTEGER_VALUE_0 : // new ComparisonValue(this, other); } diff --git a/src/proguard/evaluation/value/SpecificFloatValue.java b/src/proguard/evaluation/value/SpecificFloatValue.java index d88baa3..66e245a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -157,7 +157,7 @@ abstract class SpecificFloatValue extends FloatValue // Not handling NaN properly. //return this.equals(other) ? - // SpecificValueFactory.INTEGER_VALUE_0 : + // ParticularValueFactory.INTEGER_VALUE_0 : // new ComparisonValue(this, other); } diff --git a/src/proguard/evaluation/value/SpecificIntegerValue.java b/src/proguard/evaluation/value/SpecificIntegerValue.java index 81f8646..352e385 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -208,14 +208,14 @@ abstract class SpecificIntegerValue extends IntegerValue public IntegerValue subtract(SpecificIntegerValue other) { return this.equals(other) ? - SpecificValueFactory.INTEGER_VALUE_0 : + ParticularValueFactory.INTEGER_VALUE_0 : new CompositeIntegerValue(this, CompositeIntegerValue.SUBTRACT, other); } public IntegerValue subtractFrom(SpecificIntegerValue other) { return this.equals(other) ? - SpecificValueFactory.INTEGER_VALUE_0 : + ParticularValueFactory.INTEGER_VALUE_0 : new CompositeIntegerValue(other, CompositeIntegerValue.SUBTRACT, this); } @@ -310,7 +310,7 @@ abstract class SpecificIntegerValue extends IntegerValue public IntegerValue xor(SpecificIntegerValue other) { return this.equals(other) ? - SpecificValueFactory.INTEGER_VALUE_0 : + ParticularValueFactory.INTEGER_VALUE_0 : new CompositeIntegerValue(other, CompositeIntegerValue.XOR, this); } diff --git a/src/proguard/evaluation/value/SpecificLongValue.java b/src/proguard/evaluation/value/SpecificLongValue.java index 15138b4..162f9fe 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,14 +153,14 @@ abstract class SpecificLongValue extends LongValue public LongValue subtract(SpecificLongValue other) { return this.equals(other) ? - SpecificValueFactory.LONG_VALUE_0 : + ParticularValueFactory.LONG_VALUE_0 : new CompositeLongValue(this, CompositeLongValue.SUBTRACT, other); } public LongValue subtractFrom(SpecificLongValue other) { return this.equals(other) ? - SpecificValueFactory.LONG_VALUE_0 : + ParticularValueFactory.LONG_VALUE_0 : new CompositeLongValue(other, CompositeLongValue.SUBTRACT, this); } @@ -225,7 +225,7 @@ abstract class SpecificLongValue extends LongValue public LongValue xor(SpecificLongValue other) { return this.equals(other) ? - SpecificValueFactory.LONG_VALUE_0 : + ParticularValueFactory.LONG_VALUE_0 : new CompositeLongValue(other, CompositeLongValue.XOR, this); } diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/TopValue.java index c7320fa..4422f69 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/TypedReferenceValue.java b/src/proguard/evaluation/value/TypedReferenceValue.java new file mode 100644 index 0000000..4f8629c --- /dev/null +++ b/src/proguard/evaluation/value/TypedReferenceValue.java @@ -0,0 +1,613 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.value; + +import proguard.classfile.*; +import proguard.classfile.util.ClassUtil; +import proguard.classfile.visitor.ClassCollector; + +import java.util.*; + +/** + * This ReferenceValue represents a partially evaluated reference value. + * It has a type and a flag that indicates whether the value could be + * <code>null</code>. If the type is <code>null</code>, the value is + * <code>null</code>. + * + * @author Eric Lafortune + */ +public class TypedReferenceValue extends ReferenceValue +{ + private static final boolean DEBUG = false; + + + protected final String type; + protected final Clazz referencedClass; + protected final boolean mayBeNull; + + + /** + * Creates a new TypedReferenceValue. + */ + public TypedReferenceValue(String type, + Clazz referencedClass, + boolean mayBeNull) + { + this.type = type; + this.referencedClass = referencedClass; + this.mayBeNull = mayBeNull; + } + + + // Implementations for ReferenceValue. + + public String getType() + { + return type; + } + + + public Clazz getReferencedClass() + { + return referencedClass; + } + + + // Implementations of unary methods of ReferenceValue. + + public int isNull() + { + return type == null ? ALWAYS : + mayBeNull ? MAYBE : + NEVER; + } + + + public int instanceOf(String otherType, Clazz otherReferencedClass) + { + String thisType = this.type; + + // If this type is null, it is never an instance of any class. + if (thisType == null) + { + return NEVER; + } + + // Start taking into account the type dimensions. + int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType); + int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType); + int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount); + + // Strip any common array prefixes. + thisType = thisType.substring(commonDimensionCount); + otherType = otherType.substring(commonDimensionCount); + + // If either stripped type is a primitive type, we can tell right away. + if (commonDimensionCount > 0 && + (ClassUtil.isInternalPrimitiveType(thisType.charAt(0)) || + ClassUtil.isInternalPrimitiveType(otherType.charAt(0)))) + { + return !thisType.equals(otherType) ? NEVER : + mayBeNull ? MAYBE : + ALWAYS; + } + + // Strip the class type prefix and suffix of this type, if any. + if (thisDimensionCount == commonDimensionCount) + { + thisType = ClassUtil.internalClassNameFromClassType(thisType); + } + + // Strip the class type prefix and suffix of the other type, if any. + if (otherDimensionCount == commonDimensionCount) + { + otherType = ClassUtil.internalClassNameFromClassType(otherType); + } + + // If this type is an array type, and the other type is not + // java.lang.Object, java.lang.Cloneable, or java.io.Serializable, + // this type can never be an instance. + if (thisDimensionCount > otherDimensionCount && + !ClassUtil.isInternalArrayInterfaceName(otherType)) + { + return NEVER; + } + + // If the other type is an array type, and this type is not + // java.lang.Object, java.lang.Cloneable, or java.io.Serializable, + // this type can never be an instance. + if (thisDimensionCount < otherDimensionCount && + !ClassUtil.isInternalArrayInterfaceName(thisType)) + { + return NEVER; + } + + // If this type may be null, it might not be an instance of any class. + if (mayBeNull) + { + return MAYBE; + } + + // If this type is equal to the other type, or if the other type is + // java.lang.Object, this type is always an instance. + if (thisType.equals(otherType) || + ClassConstants.NAME_JAVA_LANG_OBJECT.equals(otherType)) + { + return ALWAYS; + } + + // If this type is an array type, it's ok. + if (thisDimensionCount > otherDimensionCount) + { + return ALWAYS; + } + + // If the other type is an array type, it might be ok. + if (thisDimensionCount < otherDimensionCount) + { + return MAYBE; + } + + // If the value extends the type, we're sure. + return referencedClass != null && + otherReferencedClass != null && + referencedClass.extendsOrImplements(otherReferencedClass) ? + ALWAYS : + MAYBE; + } + + + public ReferenceValue generalizeMayBeNull(boolean mayBeNull) + { + return this.mayBeNull == mayBeNull ? + this : + new TypedReferenceValue(type, referencedClass, true); + } + + + public ReferenceValue referenceArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + return + type == null ? ValueFactory.REFERENCE_VALUE_NULL : + !ClassUtil.isInternalArrayType(type) ? ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : + valueFactory.createValue(type.substring(1), + referencedClass, + true).referenceValue(); + } + + + // Implementations of binary methods of ReferenceValue. + + public ReferenceValue generalize(ReferenceValue other) + { + return other.generalize(this); + } + + + public int equal(ReferenceValue other) + { + return other.equal(this); + } + + + // Implementations of binary ReferenceValue methods with TypedReferenceValue + // arguments. + + public ReferenceValue generalize(TypedReferenceValue other) + { + // If both types are identical, the generalization is the same too. + if (this.equals(other)) + { + return this; + } + + String thisType = this.type; + String otherType = other.type; + + // If both types are nul, the generalization is null too. + if (thisType == null && otherType == null) + { + return ValueFactory.REFERENCE_VALUE_NULL; + } + + // If this type is null, the generalization is the other type, maybe null. + if (thisType == null) + { + return other.generalizeMayBeNull(true); + } + + // If the other type is null, the generalization is this type, maybe null. + if (otherType == null) + { + return this.generalizeMayBeNull(true); + } + + boolean mayBeNull = this.mayBeNull || other.mayBeNull; + + // If the two types are equal, the generalization remains the same, maybe null. + if (thisType.equals(otherType)) + { + return typedReferenceValue(this, mayBeNull); + } + + // Start taking into account the type dimensions. + int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType); + int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType); + int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount); + + if (thisDimensionCount == otherDimensionCount) + { + // See if we can take into account the referenced classes. + Clazz thisReferencedClass = this.referencedClass; + Clazz otherReferencedClass = other.referencedClass; + + if (thisReferencedClass != null && + otherReferencedClass != null) + { + // Is one class simply an extension of the other one? + if (thisReferencedClass.extendsOrImplements(otherReferencedClass)) + { + return typedReferenceValue(other, mayBeNull); + } + + if (otherReferencedClass.extendsOrImplements(thisReferencedClass)) + { + return typedReferenceValue(this, mayBeNull); + } + + // Do the classes have a non-trivial common superclass? + Clazz commonClass = findCommonClass(thisReferencedClass, + otherReferencedClass, + false); + + if (commonClass.getName().equals(ClassConstants.NAME_JAVA_LANG_OBJECT)) + { + // Otherwise, do the classes have a common interface? + Clazz commonInterface = findCommonClass(thisReferencedClass, + otherReferencedClass, + true); + if (commonInterface != null) + { + commonClass = commonInterface; + } + } + + return new TypedReferenceValue(commonDimensionCount == 0 ? + commonClass.getName() : + ClassUtil.internalArrayTypeFromClassName(commonClass.getName(), + commonDimensionCount), + commonClass, + mayBeNull); + } + } + else if (thisDimensionCount > otherDimensionCount) + { + // See if the other type is an interface type of arrays. + if (ClassUtil.isInternalArrayInterfaceName(ClassUtil.internalClassNameFromClassType(otherType))) + { + return typedReferenceValue(other, mayBeNull); + } + } + else if (thisDimensionCount < otherDimensionCount) + { + // See if this type is an interface type of arrays. + if (ClassUtil.isInternalArrayInterfaceName(ClassUtil.internalClassNameFromClassType(thisType))) + { + return typedReferenceValue(this, mayBeNull); + } + } + + // Reduce the common dimension count if either type is an array of + // primitives type of this dimension. + if (commonDimensionCount > 0 && + (ClassUtil.isInternalPrimitiveType(otherType.charAt(commonDimensionCount))) || + ClassUtil.isInternalPrimitiveType(thisType.charAt(commonDimensionCount))) + { + commonDimensionCount--; + } + + // Fall back on a basic Object or array of Objects type. + return + commonDimensionCount != 0 ? + new TypedReferenceValue(ClassUtil.internalArrayTypeFromClassName(ClassConstants.NAME_JAVA_LANG_OBJECT, commonDimensionCount), + null, + mayBeNull) : + mayBeNull ? + ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : + ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL; + } + + + /** + * Returns the most specific common superclass or interface of the given + * classes. + * @param class1 the first class. + * @param class2 the second class. + * @param interfaces specifies whether to look for a superclass or for an + * interface. + * @return the common class. + */ + private Clazz findCommonClass(Clazz class1, + Clazz class2, + boolean interfaces) + { + // Collect the superclasses or the interfaces of this class. + Set superClasses1 = new HashSet(); + class1.hierarchyAccept(!interfaces, + !interfaces, + interfaces, + false, + new ClassCollector(superClasses1)); + + int superClasses1Count = superClasses1.size(); + if (superClasses1Count == 0) + { + if (interfaces) + { + return null; + } + else if (class1.getSuperName() != null) + { + throw new IllegalArgumentException("Can't find any super classes of ["+class1.getName()+"] (not even immediate super class ["+class1.getSuperName()+"])"); + } + } + + // Collect the superclasses or the interfaces of the other class. + Set superClasses2 = new HashSet(); + class2.hierarchyAccept(!interfaces, + !interfaces, + interfaces, + false, + new ClassCollector(superClasses2)); + + int superClasses2Count = superClasses2.size(); + if (superClasses2Count == 0) + { + if (interfaces) + { + return null; + } + else if (class2.getSuperName() != null) + { + throw new IllegalArgumentException("Can't find any super classes of ["+class2.getName()+"] (not even immediate super class ["+class2.getSuperName()+"])"); + } + } + + if (DEBUG) + { + System.out.println("ReferenceValue.generalize this ["+class1.getName()+"] with other ["+class2.getName()+"] (interfaces = "+interfaces+")"); + System.out.println(" This super classes: "+superClasses1); + System.out.println(" Other super classes: "+superClasses2); + } + + // Find the common superclasses. + superClasses1.retainAll(superClasses2); + + if (DEBUG) + { + System.out.println(" Common super classes: "+superClasses1); + } + + if (interfaces && superClasses1.isEmpty()) + { + return null; + } + + // Find a class that is a subclass of all common superclasses, + // or that at least has the maximum number of common superclasses. + Clazz commonClass = null; + + int maximumSuperClassCount = -1; + + // Go over all common superclasses to find it. In case of + // multiple subclasses, keep the lowest one alphabetically, + // in order to ensure that the choice is deterministic. + Iterator commonSuperClasses = superClasses1.iterator(); + while (commonSuperClasses.hasNext()) + { + Clazz commonSuperClass = (Clazz)commonSuperClasses.next(); + + int superClassCount = superClassCount(commonSuperClass, superClasses1); + if (maximumSuperClassCount < superClassCount || + (maximumSuperClassCount == superClassCount && + commonClass != null && + commonClass.getName().compareTo(commonSuperClass.getName()) > 0)) + { + commonClass = commonSuperClass; + maximumSuperClassCount = superClassCount; + } + } + + if (commonClass == null) + { + throw new IllegalArgumentException("Can't find common super class of ["+ + class1.getName() +"] (with "+superClasses1Count +" known super classes) and ["+ + class2.getName()+"] (with "+superClasses2Count+" known super classes)"); + } + + if (DEBUG) + { + System.out.println(" Best common class: ["+commonClass.getName()+"]"); + } + + return commonClass; + } + + + /** + * Returns the given reference value that may or may not be null, ensuring + * that it is a TypedReferenceValue, not a subclass. + */ + private static ReferenceValue typedReferenceValue(TypedReferenceValue referenceValue, + boolean mayBeNull) + { + return referenceValue.getClass() == TypedReferenceValue.class ? + referenceValue.generalizeMayBeNull(mayBeNull) : + new TypedReferenceValue(referenceValue.type, + referenceValue.referencedClass, + mayBeNull); + } + + + /** + * Returns if the number of superclasses of the given class in the given + * set of classes. + */ + private int superClassCount(Clazz subClass, Set classes) + { + int count = 0; + + Iterator iterator = classes.iterator(); + + while (iterator.hasNext()) + { + Clazz clazz = (Clazz)iterator.next(); + if (subClass.extendsOrImplements(clazz)) + { + count++; + } + } + + return count; + } + + + public int equal(TypedReferenceValue other) + { + return this.type == null && other.type == null ? ALWAYS : MAYBE; + } + + + // Implementations of binary ReferenceValue methods with + // IdentifiedReferenceValue arguments. + + public ReferenceValue generalize(IdentifiedReferenceValue other) + { + return generalize((TypedReferenceValue)other); + } + + + public int equal(IdentifiedReferenceValue other) + { + return equal((TypedReferenceValue)other); + } + + + // Implementations of binary ReferenceValue methods with + // ArrayReferenceValue arguments. + + public ReferenceValue generalize(ArrayReferenceValue other) + { + return generalize((TypedReferenceValue)other); + } + + + public int equal(ArrayReferenceValue other) + { + return equal((TypedReferenceValue)other); + } + + + // Implementations of binary ReferenceValue methods with + // IdentifiedArrayReferenceValue arguments. + + public ReferenceValue generalize(IdentifiedArrayReferenceValue other) + { + return generalize((ArrayReferenceValue)other); + } + + + public int equal(IdentifiedArrayReferenceValue other) + { + return equal((ArrayReferenceValue)other); + } + + + // Implementations of binary ReferenceValue methods with + // DetailedArrayReferenceValue arguments. + + public ReferenceValue generalize(DetailedArrayReferenceValue other) + { + return generalize((IdentifiedArrayReferenceValue)other); + } + + + public int equal(DetailedArrayReferenceValue other) + { + return equal((IdentifiedArrayReferenceValue)other); + } + + + // Implementations for Value. + + public boolean isParticular() + { + return type == null; + } + + + public final String internalType() + { + return + type == null ? ClassConstants.TYPE_JAVA_LANG_OBJECT : + ClassUtil.isInternalArrayType(type) ? type : + ClassConstants.TYPE_CLASS_START + + type + + ClassConstants.TYPE_CLASS_END; + } + + + // Implementations for Object. + + public boolean equals(Object object) + { + if (this == object) + { + return true; + } + + if (object == null || + this.getClass() != object.getClass()) + { + return false; + } + + TypedReferenceValue other = (TypedReferenceValue)object; + return this.type == null ? other.type == null : + (this.mayBeNull == other.mayBeNull && + this.type.equals(other.type)); + } + + + public int hashCode() + { + return this.getClass().hashCode() ^ + (type == null ? 0 : type.hashCode() ^ (mayBeNull ? 0 : 1)); + } + + + public String toString() + { + return type == null ? + "null" : + type + (referencedClass == null ? "?" : "") + (mayBeNull ? "" : "!"); + } +} diff --git a/src/proguard/evaluation/value/UnknownDoubleValue.java b/src/proguard/evaluation/value/UnknownDoubleValue.java index f8bad9a..ad2f511 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 464ceed..f6f2047 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/evaluation/value/UnknownIntegerValue.java b/src/proguard/evaluation/value/UnknownIntegerValue.java index b273b12..5c05721 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 ee315be..ced2d1f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 f8d9327..5cfd02c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +45,7 @@ public abstract class Value */ public Category1Value category1Value() { - throw new IllegalArgumentException("Value is not a Category 1 value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a Category 1 value [" + this.getClass().getName() + "]"); } /** @@ -53,7 +53,7 @@ public abstract class Value */ public Category2Value category2Value() { - throw new IllegalArgumentException("Value is not a Category 2 value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a Category 2 value [" + this.getClass().getName() + "]"); } @@ -62,7 +62,7 @@ public abstract class Value */ public IntegerValue integerValue() { - throw new IllegalArgumentException("Value is not an integer value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not an integer value [" + this.getClass().getName() + "]"); } /** @@ -70,7 +70,7 @@ public abstract class Value */ public LongValue longValue() { - throw new IllegalArgumentException("Value is not a long value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a long value [" + this.getClass().getName() + "]"); } /** @@ -78,7 +78,7 @@ public abstract class Value */ public FloatValue floatValue() { - throw new IllegalArgumentException("Value is not a float value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a float value [" + this.getClass().getName() + "]"); } /** @@ -86,7 +86,7 @@ public abstract class Value */ public DoubleValue doubleValue() { - throw new IllegalArgumentException("Value is not a double value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a double value [" + this.getClass().getName() + "]"); } /** @@ -94,7 +94,7 @@ public abstract class Value */ public ReferenceValue referenceValue() { - throw new IllegalArgumentException("Value is not a reference value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a reference value [" + this.getClass().getName() + "]"); } /** @@ -102,7 +102,7 @@ public abstract class Value */ public InstructionOffsetValue instructionOffsetValue() { - throw new IllegalArgumentException("Value is not an instruction offset value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not an instruction offset value [" + this.getClass().getName() + "]"); } @@ -154,15 +154,15 @@ public abstract class Value /** * Returns the internal type of this Value. - * @return <code>ClassConstants.INTERNAL_TYPE_BOOLEAN</code>, - * <code>ClassConstants.INTERNAL_TYPE_BYTE</code>, - * <code>ClassConstants.INTERNAL_TYPE_CHAR</code>, - * <code>ClassConstants.INTERNAL_TYPE_SHORT</code>, - * <code>ClassConstants.INTERNAL_TYPE_INT</code>, - * <code>ClassConstants.INTERNAL_TYPE_LONG</code>, - * <code>ClassConstants.INTERNAL_TYPE_FLOAT</code>, - * <code>ClassConstants.INTERNAL_TYPE_DOUBLE</code>, - * <code>ClassConstants.INTERNAL_TYPE_CLASS_START ... ClassConstants.INTERNAL_TYPE_CLASS_END</code>, or + * @return <code>ClassConstants.TYPE_BOOLEAN</code>, + * <code>ClassConstants.TYPE_BYTE</code>, + * <code>ClassConstants.TYPE_CHAR</code>, + * <code>ClassConstants.TYPE_SHORT</code>, + * <code>ClassConstants.TYPE_INT</code>, + * <code>ClassConstants.TYPE_LONG</code>, + * <code>ClassConstants.TYPE_FLOAT</code>, + * <code>ClassConstants.TYPE_DOUBLE</code>, + * <code>ClassConstants.TYPE_CLASS_START ... ClassConstants.TYPE_CLASS_END</code>, or * an array type containing any of these types (always as String). */ public abstract String internalType(); diff --git a/src/proguard/evaluation/value/ValueFactory.java b/src/proguard/evaluation/value/ValueFactory.java index c94ac65..cb9e657 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +36,9 @@ public class ValueFactory static final FloatValue FLOAT_VALUE = new UnknownFloatValue(); static final DoubleValue DOUBLE_VALUE = new UnknownDoubleValue(); - static final ReferenceValue REFERENCE_VALUE_NULL = new ReferenceValue(null, null, true); - static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL = new ReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT, null, true); - static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL = new ReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT, null, false); + static final ReferenceValue REFERENCE_VALUE_NULL = new TypedReferenceValue(null, null, true); + static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL = new TypedReferenceValue(ClassConstants.NAME_JAVA_LANG_OBJECT, null, true); + static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL = new TypedReferenceValue(ClassConstants.NAME_JAVA_LANG_OBJECT, null, false); /** @@ -50,20 +50,20 @@ public class ValueFactory { switch (type.charAt(0)) { - case ClassConstants.INTERNAL_TYPE_VOID: return null; - case ClassConstants.INTERNAL_TYPE_BOOLEAN: - case ClassConstants.INTERNAL_TYPE_BYTE: - case ClassConstants.INTERNAL_TYPE_CHAR: - case ClassConstants.INTERNAL_TYPE_SHORT: - case ClassConstants.INTERNAL_TYPE_INT: return createIntegerValue(); - case ClassConstants.INTERNAL_TYPE_LONG: return createLongValue(); - case ClassConstants.INTERNAL_TYPE_FLOAT: return createFloatValue(); - case ClassConstants.INTERNAL_TYPE_DOUBLE: return createDoubleValue(); - default: return createReferenceValue(ClassUtil.isInternalArrayType(type) ? - type : - ClassUtil.internalClassNameFromClassType(type), - referencedClass, - mayBeNull); + case ClassConstants.TYPE_VOID: return null; + case ClassConstants.TYPE_BOOLEAN: + case ClassConstants.TYPE_BYTE: + case ClassConstants.TYPE_CHAR: + case ClassConstants.TYPE_SHORT: + case ClassConstants.TYPE_INT: return createIntegerValue(); + case ClassConstants.TYPE_LONG: return createLongValue(); + case ClassConstants.TYPE_FLOAT: return createFloatValue(); + case ClassConstants.TYPE_DOUBLE: return createDoubleValue(); + default: return createReferenceValue(ClassUtil.isInternalArrayType(type) ? + type : + ClassUtil.internalClassNameFromClassType(type), + referencedClass, + mayBeNull); } } @@ -153,10 +153,10 @@ public class ValueFactory Clazz referencedClass, boolean mayBeNull) { - return type == null ? REFERENCE_VALUE_NULL : - !type.equals(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT) ? new ReferenceValue(type, referencedClass, mayBeNull) : - mayBeNull ? REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : - REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL; + return type == null ? REFERENCE_VALUE_NULL : + !type.equals(ClassConstants.NAME_JAVA_LANG_OBJECT) ? new TypedReferenceValue(type, referencedClass, mayBeNull) : + mayBeNull ? REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : + REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL; } @@ -169,24 +169,7 @@ public class ValueFactory Clazz referencedClass, IntegerValue arrayLength) { - return createArrayReferenceValue(type, - referencedClass, - arrayLength, - createValue(type, referencedClass, false)); - } - - - /** - * Creates a new ReferenceValue for arrays of the given type and length, - * containing the given element. The type must be a fully specified internal - * type for primitives, classes, or arrays. - */ - public ReferenceValue createArrayReferenceValue(String type, - Clazz referencedClass, - IntegerValue arrayLength, - Value elementValue) - { - return createReferenceValue(ClassConstants.INTERNAL_TYPE_ARRAY + type, + return createReferenceValue(ClassConstants.TYPE_ARRAY + type, referencedClass, false); } diff --git a/src/proguard/gradle/ProGuardTask.java b/src/proguard/gradle/ProGuardTask.java index f5f96e8..447c630 100644 --- a/src/proguard/gradle/ProGuardTask.java +++ b/src/proguard/gradle/ProGuardTask.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.gradle; import groovy.lang.Closure; -import org.gradle.api.*; +import org.gradle.api.DefaultTask; import org.gradle.api.file.*; import org.gradle.api.logging.*; import org.gradle.api.tasks.*; @@ -63,30 +63,109 @@ public class ProGuardTask extends DefaultTask // but package visible or protected methods are ok. @InputFiles - protected FileCollection getInJarFiles() throws ParseException + protected FileCollection getInJarFileCollection() { return getProject().files(inJarFiles); } @Optional @OutputFiles - protected FileCollection getOutJarFiles() throws ParseException + protected FileCollection getOutJarFileCollection() { return getProject().files(outJarFiles); } @InputFiles - protected FileCollection getLibraryJarFiles() throws ParseException + protected FileCollection getLibraryJarFileCollection() { return getProject().files(libraryJarFiles); } @InputFiles - protected FileCollection getConfigurationFiles() throws ParseException + protected FileCollection getConfigurationFileCollection() { return getProject().files(configurationFiles); } + // Convenience methods to retrieve settings from outside the task. + + /** + * Returns the collected list of input files (directory, jar, aar, etc, + * represented as Object, String, File, etc). + */ + public List getInJarFiles() + { + return inJarFiles; + } + + /** + * Returns the collected list of filters (represented as argument Maps) + * corresponding to the list of input files. + */ + public List getInJarFilters() + { + return inJarFilters; + } + + /** + * Returns the collected list of output files (directory, jar, aar, etc, + * represented as Object, String, File, etc). + */ + public List getOutJarFiles() + { + return outJarFiles; + } + + /** + * Returns the collected list of filters (represented as argument Maps) + * corresponding to the list of output files. + */ + public List getOutJarFilters() + { + return outJarFilters; + } + + /** + * Returns the list with the numbers of input files that correspond to the + * list of output files. + * + * For instance, [2, 3] means that + * the contents of the first 2 input files go to the first output file and + * the contents of the next 3 input files go to the second output file. + */ + public List getInJarCounts() + { + return inJarCounts; + } + + /** + * Returns the collected list of library files (directory, jar, aar, etc, + * represented as Object, String, File, etc). + */ + public List getLibraryJarFiles() + { + return libraryJarFiles; + } + + /** + * Returns the collected list of filters (represented as argument Maps) + * corresponding to the list of library files. + */ + public List getLibraryJarFilters() + { + return libraryJarFilters; + } + + /** + * Returns the collected list of configuration files to be included + * (represented as Object, String, File, etc). + */ + public List getConfigurationFiles() + { + return configurationFiles; + } + + // Gradle task settings corresponding to all ProGuard options. public void configuration(Object configurationFiles) @@ -120,7 +199,7 @@ public class ProGuardTask extends DefaultTask throws ParseException { // Just collect the arguments, so they can be resolved lazily. - this.outJarFiles.add(getProject().file(outJarFiles)); + this.outJarFiles.add(outJarFiles); this.outJarFilters.add(filterArgs); this.inJarCounts.add(Integer.valueOf(inJarFiles.size())); } @@ -985,6 +1064,24 @@ public class ProGuardTask extends DefaultTask public void proguard() throws ParseException, IOException { + // 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(getConfiguration()).execute(); + + } + + + /** + * Returns the configuration collected so far, resolving files and + * reading included configurations. + */ + private Configuration getConfiguration() throws IOException, ParseException + { // Weave the input jars and the output jars into a single class path, // with lazy resolution of the files. configuration.programJars = new ClassPath(); @@ -1054,15 +1151,7 @@ public class ProGuardTask extends DefaultTask // 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(); - + return configuration; } @@ -1097,7 +1186,9 @@ public class ProGuardTask extends DefaultTask if (filterArgs != null) { classPathEntry.setFilter(ListUtil.commaSeparatedList((String)filterArgs.get("filter"))); + classPathEntry.setApkFilter(ListUtil.commaSeparatedList((String)filterArgs.get("apkfilter"))); classPathEntry.setJarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("jarfilter"))); + classPathEntry.setAarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("aarfilter"))); classPathEntry.setWarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("warfilter"))); classPathEntry.setEarFilter(ListUtil.commaSeparatedList((String)filterArgs.get("earfilter"))); classPathEntry.setZipFilter(ListUtil.commaSeparatedList((String)filterArgs.get("zipfilter"))); @@ -1170,9 +1261,10 @@ public class ProGuardTask extends DefaultTask return new KeepClassSpecification(markClasses, markConditionally, - retrieveBoolean(keepArgs, "allowshrinking", allowShrinking), - retrieveBoolean(keepArgs, "allowoptimization", false), - retrieveBoolean(keepArgs, "allowobfuscation", false), + retrieveBoolean(keepArgs, "includedescriptorclasses", false), + retrieveBoolean(keepArgs, "allowshrinking", allowShrinking), + retrieveBoolean(keepArgs, "allowoptimization", false), + retrieveBoolean(keepArgs, "allowobfuscation", false), classSpecification); } @@ -1274,11 +1366,11 @@ public class ProGuardTask extends DefaultTask 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 : + strippedToken.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC : + strippedToken.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL : + strippedToken.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT : + strippedToken.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC : + strippedToken.equals(JavaConstants.ACC_ANNOTATION) ? ClassConstants.ACC_ANNOTATTION : 0; if (accessFlag == 0) @@ -1295,10 +1387,10 @@ public class ProGuardTask extends DefaultTask { 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 : + type.equals( JavaConstants.ACC_INTERFACE) || + type.equals("!" + JavaConstants.ACC_INTERFACE) ? ClassConstants.ACC_INTERFACE : + type.equals( JavaConstants.ACC_ENUM) || + type.equals("!" + JavaConstants.ACC_ENUM) ? ClassConstants.ACC_ENUM : -1; if (accessFlag == -1) { @@ -1344,10 +1436,10 @@ public class ProGuardTask extends DefaultTask if (parameters != null) { - type = ClassConstants.EXTERNAL_TYPE_VOID; + type = JavaConstants.TYPE_VOID; } - name = ClassConstants.INTERNAL_METHOD_NAME_INIT; + name = ClassConstants.METHOD_NAME_INIT; } else if ((type != null) ^ (parameters != null)) { @@ -1401,20 +1493,20 @@ public class ProGuardTask extends DefaultTask 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 : + strippedToken.equals(JavaConstants.ACC_PUBLIC) ? ClassConstants.ACC_PUBLIC : + strippedToken.equals(JavaConstants.ACC_PRIVATE) ? ClassConstants.ACC_PRIVATE : + strippedToken.equals(JavaConstants.ACC_PROTECTED) ? ClassConstants.ACC_PROTECTED : + strippedToken.equals(JavaConstants.ACC_STATIC) ? ClassConstants.ACC_STATIC : + strippedToken.equals(JavaConstants.ACC_FINAL) ? ClassConstants.ACC_FINAL : + strippedToken.equals(JavaConstants.ACC_SYNCHRONIZED) ? ClassConstants.ACC_SYNCHRONIZED : + strippedToken.equals(JavaConstants.ACC_VOLATILE) ? ClassConstants.ACC_VOLATILE : + strippedToken.equals(JavaConstants.ACC_TRANSIENT) ? ClassConstants.ACC_TRANSIENT : + strippedToken.equals(JavaConstants.ACC_BRIDGE) ? ClassConstants.ACC_BRIDGE : + strippedToken.equals(JavaConstants.ACC_VARARGS) ? ClassConstants.ACC_VARARGS : + strippedToken.equals(JavaConstants.ACC_NATIVE) ? ClassConstants.ACC_NATIVE : + strippedToken.equals(JavaConstants.ACC_ABSTRACT) ? ClassConstants.ACC_ABSTRACT : + strippedToken.equals(JavaConstants.ACC_STRICT) ? ClassConstants.ACC_STRICT : + strippedToken.equals(JavaConstants.ACC_SYNTHETIC) ? ClassConstants.ACC_SYNTHETIC : 0; if (accessFlag == 0) diff --git a/src/proguard/gui/ClassPathPanel.java b/src/proguard/gui/ClassPathPanel.java index 8f41db6..1b61f0f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.*; +import java.io.File; import java.util.List; /** @@ -58,8 +58,8 @@ class ClassPathPanel extends ListPanel chooser.setMultiSelectionEnabled(true); chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); chooser.addChoosableFileFilter( - new ExtensionFileFilter(msg("jarWarEarZipExtensions"), - new String[] { ".jar", ".war", ".ear", ".zip" })); + new ExtensionFileFilter(msg("jarExtensions"), + new String[] { ".apk", ".ap_", ".jar", ".aar", ".war", ".ear", ".zip" })); chooser.setApproveButtonText(msg("ok")); filterDialog = new FilterDialog(owner, msg("enterFilter")); @@ -267,7 +267,9 @@ class ClassPathPanel extends ListPanel ClassPathEntry firstEntry = (ClassPathEntry)listModel.get(index); filterDialog.setFilter(firstEntry.getFilter()); + filterDialog.setApkFilter(firstEntry.getApkFilter()); filterDialog.setJarFilter(firstEntry.getJarFilter()); + filterDialog.setAarFilter(firstEntry.getAarFilter()); filterDialog.setWarFilter(firstEntry.getWarFilter()); filterDialog.setEarFilter(firstEntry.getEarFilter()); filterDialog.setZipFilter(firstEntry.getZipFilter()); @@ -284,7 +286,9 @@ class ClassPathPanel extends ListPanel { ClassPathEntry entry = (ClassPathEntry)listModel.get(indices[index]); entry.setFilter(filterDialog.getFilter()); + entry.setApkFilter(filterDialog.getApkFilter()); entry.setJarFilter(filterDialog.getJarFilter()); + entry.setAarFilter(filterDialog.getAarFilter()); entry.setWarFilter(filterDialog.getWarFilter()); entry.setEarFilter(filterDialog.getEarFilter()); entry.setZipFilter(filterDialog.getZipFilter()); @@ -381,7 +385,9 @@ class ClassPathPanel extends ListPanel filter = appendFilter(filter, entry.getZipFilter()); filter = appendFilter(filter, entry.getEarFilter()); filter = appendFilter(filter, entry.getWarFilter()); + filter = appendFilter(filter, entry.getAarFilter()); filter = appendFilter(filter, entry.getJarFilter()); + filter = appendFilter(filter, entry.getApkFilter()); filter = appendFilter(filter, entry.getFilter()); if (filter != null) diff --git a/src/proguard/gui/ClassSpecificationDialog.java b/src/proguard/gui/ClassSpecificationDialog.java index 38a3146..f6686ec 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -55,6 +55,8 @@ final class ClassSpecificationDialog extends JDialog private final JRadioButton keepClassMembersRadioButton = new JRadioButton(msg("keepClassMembers")); private final JRadioButton keepClassesWithMembersRadioButton = new JRadioButton(msg("keepClassesWithMembers")); + private final JCheckBox keepDescriptorClassesCheckBox = new JCheckBox(msg("keepDescriptorClasses")); + private final JCheckBox allowShrinkingCheckBox = new JCheckBox(msg("allowShrinking")); private final JCheckBox allowOptimizationCheckBox = new JCheckBox(msg("allowOptimization")); private final JCheckBox allowObfuscationCheckBox = new JCheckBox(msg("allowObfuscation")); @@ -176,6 +178,14 @@ final class ClassSpecificationDialog extends JDialog keepOptionPanel.add(tip(keepClassesAndMembersRadioButton, "keepTip"), constraintsLastStretch); keepOptionPanel.add(tip(keepClassMembersRadioButton, "keepClassMembersTip"), constraintsLastStretch); keepOptionPanel.add(tip(keepClassesWithMembersRadioButton, "keepClassesWithMembersTip"), constraintsLastStretch); + keepOptionPanel.add(tip(keepDescriptorClassesCheckBox, "keepDescriptorClassesTip"), constraintsLastStretch); + + // Create the also keep panel. + final JPanel alsoKeepOptionPanel = new JPanel(layout); + alsoKeepOptionPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder, + msg("alsoKeepTitle"))); + + alsoKeepOptionPanel.add(tip(keepDescriptorClassesCheckBox, "keepDescriptorClassesTip"), constraintsLastStretch); // Create the allow option panel. final JPanel allowOptionPanel = new JPanel(layout); @@ -245,8 +255,9 @@ final class ClassSpecificationDialog extends JDialog { public void actionPerformed(ActionEvent e) { - boolean visible = !allowOptionPanel.isVisible(); + boolean visible = !alsoKeepOptionPanel.isVisible(); + alsoKeepOptionPanel .setVisible(visible); allowOptionPanel .setVisible(visible); annotationTypePanel .setVisible(visible); extendsAnnotationTypePanel.setVisible(visible); @@ -285,6 +296,7 @@ final class ClassSpecificationDialog extends JDialog if (fullKeepOptions) { mainPanel.add(tip(keepOptionPanel, "keepTitleTip"), panelConstraints); + mainPanel.add(tip(alsoKeepOptionPanel, "alsoKeepTitleTip"), panelConstraints); mainPanel.add(tip(allowOptionPanel, "allowTitleTip"), panelConstraints); } mainPanel.add(tip(accessPanel, "accessTip"), panelConstraints); @@ -352,11 +364,12 @@ final class ClassSpecificationDialog extends JDialog */ public void setKeepSpecification(KeepClassSpecification keepClassSpecification) { - boolean markClasses = keepClassSpecification.markClasses; - boolean markConditionally = keepClassSpecification.markConditionally; - boolean allowShrinking = keepClassSpecification.allowShrinking; - boolean allowOptimization = keepClassSpecification.allowOptimization; - boolean allowObfuscation = keepClassSpecification.allowObfuscation; + boolean markClasses = keepClassSpecification.markClasses; + boolean markConditionally = keepClassSpecification.markConditionally; + boolean markDescriptorClasses = keepClassSpecification.markDescriptorClasses; + boolean allowShrinking = keepClassSpecification.allowShrinking; + boolean allowOptimization = keepClassSpecification.allowOptimization; + boolean allowObfuscation = keepClassSpecification.allowObfuscation; // Figure out the proper keep radio button and set it. JRadioButton keepOptionRadioButton = @@ -366,10 +379,11 @@ final class ClassSpecificationDialog extends JDialog keepOptionRadioButton.setSelected(true); - // Set the allow radio buttons. - allowShrinkingCheckBox .setSelected(allowShrinking); - allowOptimizationCheckBox.setSelected(allowOptimization); - allowObfuscationCheckBox .setSelected(allowObfuscation); + // Set the other check boxes. + keepDescriptorClassesCheckBox.setSelected(markDescriptorClasses); + allowShrinkingCheckBox .setSelected(allowShrinking); + allowOptimizationCheckBox .setSelected(allowOptimization); + allowObfuscationCheckBox .setSelected(allowObfuscation); setClassSpecification(keepClassSpecification); } @@ -392,13 +406,13 @@ final class ClassSpecificationDialog extends JDialog commentsTextArea.setText(comments == null ? "" : comments); // Set the access radio buttons. - 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_INTERFACE, interfaceRadioButtons); - setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons); - setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM, enumRadioButtons); - setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC, syntheticRadioButtons); + setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_PUBLIC, publicRadioButtons); + setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_FINAL, finalRadioButtons); + setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ABSTRACT, abstractRadioButtons); + setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_INTERFACE, interfaceRadioButtons); + setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ANNOTATTION, annotationRadioButtons); + setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ENUM, enumRadioButtons); + setClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_SYNTHETIC, syntheticRadioButtons); // Set the class and annotation text fields. annotationTypeTextField .setText(annotationType == null ? "" : ClassUtil.externalType(annotationType)); @@ -416,18 +430,20 @@ final class ClassSpecificationDialog extends JDialog */ public KeepClassSpecification getKeepSpecification() { - boolean markClasses = !keepClassMembersRadioButton .isSelected(); - boolean markConditionally = keepClassesWithMembersRadioButton.isSelected(); - boolean allowShrinking = allowShrinkingCheckBox .isSelected(); - boolean allowOptimization = allowOptimizationCheckBox .isSelected(); - boolean allowObfuscation = allowObfuscationCheckBox .isSelected(); + boolean markClasses = !keepClassMembersRadioButton .isSelected(); + boolean markConditionally = keepClassesWithMembersRadioButton.isSelected(); + boolean markDescriptorClasses = keepDescriptorClassesCheckBox .isSelected(); + boolean allowShrinking = allowShrinkingCheckBox .isSelected(); + boolean allowOptimization = allowOptimizationCheckBox .isSelected(); + boolean allowObfuscation = allowObfuscationCheckBox .isSelected(); return new KeepClassSpecification(markClasses, - markConditionally, - allowShrinking, - allowOptimization, - allowObfuscation, - getClassSpecification()); + markConditionally, + markDescriptorClasses, + allowShrinking, + allowOptimization, + allowObfuscation, + getClassSpecification()); } @@ -453,13 +469,13 @@ final class ClassSpecificationDialog extends JDialog extendsClassName.equals("") ? null : ClassUtil.internalClassName(extendsClassName)); // Also get the access radio button settings. - 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_INTERFACE, interfaceRadioButtons); - getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons); - getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM, enumRadioButtons); - getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC, syntheticRadioButtons); + getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_PUBLIC, publicRadioButtons); + getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_FINAL, finalRadioButtons); + getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ABSTRACT, abstractRadioButtons); + getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_INTERFACE, interfaceRadioButtons); + getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ANNOTATTION, annotationRadioButtons); + getClassSpecificationRadioButtons(classSpecification, ClassConstants.ACC_ENUM, enumRadioButtons); + getClassSpecificationRadioButtons(classSpecification, ClassConstants.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 bc29247..f09fbe3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 ee09714..dbaae66 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 c362cb6..cdf297c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 88dbd8b..d96684e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,18 +47,23 @@ public class FilterDialog extends JDialog public static final int APPROVE_OPTION = 0; private static final String DEFAULT_FILTER = "**"; + private static final String DEFAULT_APK_FILTER = "**.apk"; private static final String DEFAULT_JAR_FILTER = "**.jar"; + private static final String DEFAULT_AAR_FILTER = "**.aar"; private static final String DEFAULT_WAR_FILTER = "**.war"; private static final String DEFAULT_EAR_FILTER = "**.ear"; private static final String DEFAULT_ZIP_FILTER = "**.zip"; private final JTextField filterTextField = new JTextField(40); + private final JTextField apkFilterTextField = new JTextField(40); private final JTextField jarFilterTextField = new JTextField(40); + private final JTextField aarFilterTextField = new JTextField(40); private final JTextField warFilterTextField = new JTextField(40); private final JTextField earFilterTextField = new JTextField(40); private final JTextField zipFilterTextField = new JTextField(40); - private int returnValue; + + private int returnValue; public FilterDialog(JFrame owner, @@ -120,7 +125,9 @@ public class FilterDialog extends JDialog // Create the filter labels. JLabel filterLabel = new JLabel(msg("nameFilter")); + JLabel apkFilterLabel = new JLabel(msg("apkNameFilter")); JLabel jarFilterLabel = new JLabel(msg("jarNameFilter")); + JLabel aarFilterLabel = new JLabel(msg("aarNameFilter")); JLabel warFilterLabel = new JLabel(msg("warNameFilter")); JLabel earFilterLabel = new JLabel(msg("earNameFilter")); JLabel zipFilterLabel = new JLabel(msg("zipNameFilter")); @@ -135,9 +142,15 @@ public class FilterDialog extends JDialog filterPanel.add(tip(filterLabel, "nameFilterTip"), labelConstraints); filterPanel.add(tip(filterTextField, "fileNameFilterTip"), textFieldConstraints); + filterPanel.add(tip(apkFilterLabel, "apkNameFilterTip"), labelConstraints); + filterPanel.add(tip(apkFilterTextField, "fileNameFilterTip"), textFieldConstraints); + filterPanel.add(tip(jarFilterLabel, "jarNameFilterTip"), labelConstraints); filterPanel.add(tip(jarFilterTextField, "fileNameFilterTip"), textFieldConstraints); + filterPanel.add(tip(aarFilterLabel, "aarNameFilterTip"), labelConstraints); + filterPanel.add(tip(aarFilterTextField, "fileNameFilterTip"), textFieldConstraints); + filterPanel.add(tip(warFilterLabel, "warNameFilterTip"), labelConstraints); filterPanel.add(tip(warFilterTextField, "fileNameFilterTip"), textFieldConstraints); @@ -198,6 +211,26 @@ public class FilterDialog extends JDialog /** + * Sets the apk filter to be represented in this dialog. + */ + public void setApkFilter(List filter) + { + apkFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_APK_FILTER); + } + + + /** + * Returns the apk filter currently represented in this dialog. + */ + public List getApkFilter() + { + String filter = apkFilterTextField.getText(); + + return filter.equals(DEFAULT_APK_FILTER) ? null : ListUtil.commaSeparatedList(filter); + } + + + /** * Sets the jar filter to be represented in this dialog. */ public void setJarFilter(List filter) @@ -218,6 +251,26 @@ public class FilterDialog extends JDialog /** + * Sets the aar filter to be represented in this dialog. + */ + public void setAarFilter(List filter) + { + aarFilterTextField.setText(filter != null ? ListUtil.commaSeparatedString(filter, true) : DEFAULT_AAR_FILTER); + } + + + /** + * Returns the aar filter currently represented in this dialog. + */ + public List getAarFilter() + { + String filter = aarFilterTextField.getText(); + + return filter.equals(DEFAULT_AAR_FILTER) ? null : ListUtil.commaSeparatedList(filter); + } + + + /** * Sets the war filter to be represented in this dialog. */ public void setWarFilter(List filter) diff --git a/src/proguard/gui/GUIResources.java b/src/proguard/gui/GUIResources.java index 3d7c6c6..5d411ae 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 b27075d..12b6f28 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-2013 Eric Lafortune (eric@graphics.cornell.edu) +# Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) # # Tab names. @@ -25,7 +25,7 @@ preverification = Preverification # # Panel titles. # -welcome = Welcome to ProGuard, version 4.10 +welcome = Welcome to ProGuard, version 5.1 options = Options keepAdditional = Keep additional classes and class members keepNamesAdditional = Keep additional class names and class member names @@ -70,7 +70,7 @@ proGuardInfo = \ <p>\ Distributed under the GNU General Public License.\ <br>\ - Copyright © 2002-2013.</html> + Copyright © 2002-2014.</html> processingInfo = \ You can now start processing your code, \ @@ -86,8 +86,8 @@ reTraceInfo = \ # # Titles and labels corresponding to common ProGuard options. # -programJars = Program jars, wars, ears, zips, and directories -libraryJars = Library jars, wars, ears, zips, and directories +programJars = Program jars, aars, wars, ears, zips, apks, and directories +libraryJars = Library jars, aars, wars, ears, zips, apks, and directories shrink = Shrink printUsage = Print usage @@ -129,7 +129,7 @@ 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,1.7 +targets = 1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8 printSeeds = Print seeds printConfiguration = Print configuration dump = Print class files @@ -138,10 +138,10 @@ mappingFile = Mapping file obfuscatedStackTrace = Obfuscated stack trace programJarsTip = \ - <html>The input jars (wars, ears, zips, directories), followed by<br>\ - their corresponding output jars (wars, ears, zips, directories).</html> + <html>The input jars (aars, wars, ears, zips, apks, directories), followed by<br>\ + their corresponding output jars (wars, ears, zips, apks, directories).</html> libraryJarsTip = \ - <html>The library jars (wars, ears, zips, directories), on which the program jars depend.<br>\ + <html>The library jars (aars, wars, ears, zips, directories), on which the program jars depend.<br>\ The library jars are required for processing, but they are not copied to the output.</html> shrinkTip = \ @@ -270,7 +270,7 @@ skipNonPublicLibraryClassMembersTip = \ <html>Skip reading non-public library fields and methods, for efficiency.<br>\ You may have to unset this option if ProGuard complains about missing class members.</html> keepDirectoriesTip = \ - Keep the specified directories in the output jars, wars, ears, zips, or directories. + Keep the specified directories in the output jars, wars, ears, zips, apks, or directories. directoriesTip = \ <html>A filter on directory names,<br>\ e.g. <code>mydirectory1,mydirectory2/**</code><br>\ @@ -306,6 +306,10 @@ keep = Keep classes and class members keepClassMembers = Keep class members only keepClassesWithMembers = Keep classes and class members, if members are present +alsoKeepTitle = Also keep + +keepDescriptorClasses = Keep descriptor classes + allowTitle = Allow allowShrinking = Allow shrinking @@ -323,6 +327,14 @@ keepClassesWithMembersTip = \ <html>Keep the specified classes, fields, and methods,<br>\ on the condition that the fields and methods are present.</html> +alsoKeepTitleTip = \ + <html>Optionally keeping more classes.<br>\ + <i>These are advanced options.</i></html> + +keepDescriptorClassesTip = \ + <html>Automatically keep the classes in the descriptors of matching<br>\ + fields and methods. Mostly useful for keeping their names.</html> + allowTitleTip = \ <html>Optionally relax keeping the specified classes, fields, and methods.<br>\ <i>These are advanced options.</i></html> @@ -539,8 +551,8 @@ cantParseConfigurationFile = Can''t parse the configuration file [{0}] cantSaveConfigurationFile = Can''t save the configuration file [{0}] cantOpenStackTraceFile = Can''t open the stack trace file [{0}] -jarWarEarZipExtensions = *.jar, *.war, *.ear, *.zip (archives and directories) -proExtension = *.pro (ProGuard configurations) +jarExtensions = *.jar, *.aar, *.war, *.ear, *.zip, *.apk, *.ap_ (archives and directories) +proExtension = *.pro (ProGuard configurations) addJars = Add one or more jars or directories... chooseJars = Choose different jars or directories... @@ -548,7 +560,9 @@ enterFilter = Optionally filter the file names contained in the selected entries filters = Filters nameFilter = File name filter +apkNameFilter = Apk name filter jarNameFilter = Jar name filter +aarNameFilter = Aar name filter warNameFilter = War name filter earNameFilter = Ear name filter zipNameFilter = Zip name filter @@ -557,7 +571,9 @@ outputFileTip = The optional output file. inputFileTip = The input file. nameFilterTip = A filter on plain class file names and resource file names. +apkNameFilterTip = A filter on apk file names. jarNameFilterTip = A filter on jar file names. +aarNameFilterTip = A filter on aar file names. warNameFilterTip = A filter on war file names. earNameFilterTip = A filter on ear file names. zipNameFilterTip = A filter on zip file names. @@ -601,8 +617,8 @@ reTrace = ReTrace! advancedTip = Toggle between showing basic options and advanced options. -addInputTip = Add an input jar, war, ear, zip, or directory. -addOutputTip = Add an output jar, war, ear, zip, or directory. +addInputTip = Add an input jar, aar, war, ear, zip, apk, or directory. +addOutputTip = Add an output jar, aar, war, ear, zip, apk, or directory. addTip = Add an entry. editTip = Edit the selected entries. filterTip = Put filters on the contents of the selected entries. diff --git a/src/proguard/gui/KeepSpecificationsPanel.java b/src/proguard/gui/KeepSpecificationsPanel.java index 908f028..0678bc7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 @@ final class KeepSpecificationsPanel extends ClassSpecificationsPanel { private final boolean markClasses; private final boolean markConditionally; + private final boolean markDescriptorClasses; private final boolean allowShrinking; private final boolean allowOptimization; private final boolean allowObfuscation; @@ -42,17 +43,19 @@ final class KeepSpecificationsPanel extends ClassSpecificationsPanel public KeepSpecificationsPanel(JFrame owner, boolean markClasses, boolean markConditionally, + boolean markDescriptorClasses, boolean allowShrinking, boolean allowOptimization, boolean allowObfuscation) { super(owner, true); - this.markClasses = markClasses; - this.markConditionally = markConditionally; - this.allowShrinking = allowShrinking; - this.allowOptimization = allowOptimization; - this.allowObfuscation = allowObfuscation; + this.markClasses = markClasses; + this.markConditionally = markConditionally; + this.markDescriptorClasses = markDescriptorClasses; + this.allowShrinking = allowShrinking; + this.allowOptimization = allowOptimization; + this.allowObfuscation = allowObfuscation; } @@ -61,10 +64,11 @@ final class KeepSpecificationsPanel extends ClassSpecificationsPanel protected ClassSpecification createClassSpecification() { return new KeepClassSpecification(markClasses, - markConditionally, - allowShrinking, - allowOptimization, - allowObfuscation); + markConditionally, + markDescriptorClasses, + allowShrinking, + allowOptimization, + allowObfuscation); } diff --git a/src/proguard/gui/ListPanel.java b/src/proguard/gui/ListPanel.java index 19a0c4d..d0293a2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,13 +20,12 @@ */ package proguard.gui; +import javax.swing.*; +import javax.swing.event.*; import java.awt.*; import java.awt.event.*; -import java.util.List; import java.util.*; - -import javax.swing.*; -import javax.swing.event.*; +import java.util.List; /** * This <code>Jpanel</code> allows the user to move and remove entries in a diff --git a/src/proguard/gui/MemberSpecificationDialog.java b/src/proguard/gui/MemberSpecificationDialog.java index 4bf72ca..9744e9e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.gui; import proguard.MemberSpecification; -import proguard.classfile.ClassConstants; +import proguard.classfile.*; import proguard.classfile.util.ClassUtil; import proguard.util.ListUtil; @@ -333,20 +333,20 @@ final class MemberSpecificationDialog extends JDialog annotationTypeTextField.setText(annotationType == null ? "" : ClassUtil.externalType(annotationType)); // Set the access radio buttons. - setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_PUBLIC, publicRadioButtons); - setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_PRIVATE, privateRadioButtons); - 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); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PUBLIC, publicRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PRIVATE, privateRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PROTECTED, protectedRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_STATIC, staticRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_FINAL, finalRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_SYNTHETIC, syntheticRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_VOLATILE, volatileRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_TRANSIENT, transientRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_SYNCHRONIZED, synchronizedRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_NATIVE, nativeRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_ABSTRACT, abstractRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_STRICT, strictRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_BRIDGE, bridgeRadioButtons); + setMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_VARARGS, varargsRadioButtons); // Set the class name text fields. nameTextField.setText(name == null ? "*" : name); @@ -394,7 +394,7 @@ final class MemberSpecificationDialog extends JDialog { if (type.equals("")) { - type = ClassConstants.EXTERNAL_TYPE_VOID; + type = JavaConstants.TYPE_VOID; } type = @@ -407,20 +407,20 @@ final class MemberSpecificationDialog extends JDialog new MemberSpecification(0, 0, annotationType, name, type); // Also get the access radio button settings. - getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_PUBLIC, publicRadioButtons); - getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.INTERNAL_ACC_PRIVATE, privateRadioButtons); - 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); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PUBLIC, publicRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PRIVATE, privateRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_PROTECTED, protectedRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_STATIC, staticRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_FINAL, finalRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_SYNTHETIC, syntheticRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_VOLATILE, volatileRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_TRANSIENT, transientRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_SYNCHRONIZED, synchronizedRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_NATIVE, nativeRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_ABSTRACT, abstractRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_STRICT, strictRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_BRIDGE, bridgeRadioButtons); + getMemberSpecificationRadioButtons(memberSpecification, ClassConstants.ACC_VARARGS, varargsRadioButtons); return memberSpecification; } diff --git a/src/proguard/gui/MemberSpecificationsPanel.java b/src/proguard/gui/MemberSpecificationsPanel.java index 6a72a1d..92feac6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.gui; -import proguard.*; +import proguard.MemberSpecification; import proguard.classfile.ClassConstants; import proguard.classfile.util.ClassUtil; @@ -240,7 +240,7 @@ final class MemberSpecificationsPanel extends ListPanel (descriptor == null ? name == null ? "<methods>" : "***" + ' ' + name + "(...)" : - ClassUtil.externalFullMethodDescription(ClassConstants.INTERNAL_METHOD_NAME_INIT, + ClassUtil.externalFullMethodDescription(ClassConstants.METHOD_NAME_INIT, 0, name == null ? "*" : name, descriptor))); diff --git a/src/proguard/gui/MessageDialogRunnable.java b/src/proguard/gui/MessageDialogRunnable.java index 6c2152c..d1809c7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ package proguard.gui; import javax.swing.*; import java.awt.*; -import java.lang.reflect.InvocationTargetException; /** diff --git a/src/proguard/gui/OptimizationsDialog.java b/src/proguard/gui/OptimizationsDialog.java index 0af0979..c30797b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 6b08aa8..4c2ef57 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,13 +70,13 @@ public class ProGuardGUI extends JFrame private final JCheckBox[] boilerplateKeepCheckBoxes; private final JTextField[] boilerplateKeepTextFields; - private final KeepSpecificationsPanel additionalKeepPanel = new KeepSpecificationsPanel(this, true, false, false, false, false); + private final KeepSpecificationsPanel additionalKeepPanel = new KeepSpecificationsPanel(this, true, false, false, false, false, false); private KeepClassSpecification[] boilerplateKeepNames; private final JCheckBox[] boilerplateKeepNamesCheckBoxes; private final JTextField[] boilerplateKeepNamesTextFields; - private final KeepSpecificationsPanel additionalKeepNamesPanel = new KeepSpecificationsPanel(this, true, false, true, false, false); + private final KeepSpecificationsPanel additionalKeepNamesPanel = new KeepSpecificationsPanel(this, true, false, false, true, false, false); private ClassSpecification[] boilerplateNoSideEffectMethods; private final JCheckBox[] boilerplateNoSideEffectMethodCheckBoxes; diff --git a/src/proguard/gui/ProGuardRunnable.java b/src/proguard/gui/ProGuardRunnable.java index b341b7b..e03fb29 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 6f1b135..4e0f299 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 373fdc9..b7edf98 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 c6b6678..07c1a63 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 84ba562..425574c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ package proguard.gui; import javax.swing.*; import java.io.*; -import java.lang.reflect.InvocationTargetException; /** diff --git a/src/proguard/gui/boilerplate.pro b/src/proguard/gui/boilerplate.pro index 711c07d..4b35ac1 100644 --- a/src/proguard/gui/boilerplate.pro +++ b/src/proguard/gui/boilerplate.pro @@ -79,7 +79,7 @@ } # Keep names - Native method names. Keep all native class/method names. --keepclasseswithmembernames class * { +-keepclasseswithmembernames,includedescriptorclasses class * { native <methods>; } diff --git a/src/proguard/gui/default.pro b/src/proguard/gui/default.pro index 752c9b2..8cd6b38 100644 --- a/src/proguard/gui/default.pro +++ b/src/proguard/gui/default.pro @@ -25,7 +25,7 @@ } # Keep names - Native method names. Keep all native class/method names. --keepclasseswithmembers,allowshrinking class * { +-keepclasseswithmembers,includedescriptorclasses,allowshrinking class * { native <methods>; } diff --git a/src/proguard/gui/splash/BufferedSprite.java b/src/proguard/gui/splash/BufferedSprite.java index 5625acb..251088e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 0443a0c..2ce1bfd 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 a8ac368..d286bcb 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 95153a2..a5baaca 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 68cbe35..b5ad4c0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 fa7f3a5..f3439d5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 c969332..45e7a08 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 26691b9..3efc4d2 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 ff79dd0..d34be3d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 e76f1eb..534c474 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 b6a7762..a32d7ad 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 42f165d..3904432 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 f7704f9..2ef0be5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 283a1c9..34e9b45 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 bf926b0..0536af3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 46c35bc..dcd2234 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 c35348e..9c00b0d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 81a9429..1306d9a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 547b549..d65abc3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 393f27e..9158e12 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 fadca5f..9a136bc 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 ab3d0c1..bfa7388 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 a691d3c..73fea38 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 af959e9..94596e6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 f1f6e72..7f225e3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 69bd4c7..5225b90 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 dd292ad..ffafcd3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 bb15900..9d01c1d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 d304dca..83b4bd0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 ce573aa..eabcc71 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 7317403..120d7f5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 0668c38..7ca9462 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 b4523ef..e12a319 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 52b8ab2..4c1ff0f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 81ca8f6..2622889 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 62f3bf7..17c1946 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 aabc5ba..c89f9f6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +23,6 @@ package proguard.io; import proguard.classfile.ClassConstants; import proguard.util.ExtensionMatcher; -import java.io.IOException; - /** * This DataEntryReader delegates to one of two other DataEntryReader instances, diff --git a/src/proguard/io/ClassReader.java b/src/proguard/io/ClassReader.java index 0ad382b..124160c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -95,7 +95,7 @@ public class ClassReader implements DataEntryReader String className = clazz.getName(); if (className != null) { - if (!dataEntry.getName().replace(File.pathSeparatorChar, ClassConstants.INTERNAL_PACKAGE_SEPARATOR).equals(className+ClassConstants.CLASS_FILE_EXTENSION) && + if (!dataEntry.getName().replace(File.pathSeparatorChar, ClassConstants.PACKAGE_SEPARATOR).equals(className+ClassConstants.CLASS_FILE_EXTENSION) && warningPrinter != null) { warningPrinter.print(className, diff --git a/src/proguard/io/ClassRewriter.java b/src/proguard/io/ClassRewriter.java index 97e8aef..fab9366 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 681331b..59946c9 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 index e9f0327..205cce1 100644 --- a/src/proguard/io/DataEntryClassWriter.java +++ b/src/proguard/io/DataEntryClassWriter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +21,9 @@ package proguard.io; import proguard.classfile.*; -import proguard.classfile.io.*; -import proguard.classfile.util.*; -import proguard.classfile.visitor.*; +import proguard.classfile.io.ProgramClassWriter; +import proguard.classfile.util.SimplifiedVisitor; +import proguard.classfile.visitor.ClassVisitor; import java.io.*; diff --git a/src/proguard/io/DataEntryCopier.java b/src/proguard/io/DataEntryCopier.java index 440e73b..63b2fa9 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,19 +120,22 @@ public class DataEntryCopier implements DataEntryReader String input = args[0]; String output = args[1]; + boolean outputIsApk = output.endsWith(".apk") || + output.endsWith(".ap_"); boolean outputIsJar = output.endsWith(".jar"); + boolean outputIsAar = output.endsWith(".aar"); boolean outputIsWar = output.endsWith(".war"); boolean outputIsEar = output.endsWith(".ear"); boolean outputIsZip = output.endsWith(".zip"); DataEntryWriter writer = new DirectoryWriter(new File(output), + outputIsApk || outputIsJar || + outputIsAar || outputIsWar || outputIsEar || outputIsZip); - if (!outputIsJar) - { // Zip up any zips, if necessary. DataEntryWriter zipWriter = new JarWriter(writer); if (outputIsZip) @@ -150,6 +153,23 @@ public class DataEntryCopier implements DataEntryReader writer); } + // Zip up any ears, if necessary. + DataEntryWriter earWriter = new JarWriter(writer); + if (outputIsEar) + { + // Always zip. + writer = earWriter; + } + else + { + // Only zip up ears. + writer = new FilteredDataEntryWriter(new DataEntryParentFilter( + new DataEntryNameFilter( + new ExtensionMatcher(".ear"))), + earWriter, + writer); + } + // Zip up any wars, if necessary. DataEntryWriter warWriter = new JarWriter(writer); if (outputIsWar) @@ -166,79 +186,163 @@ public class DataEntryCopier implements DataEntryReader warWriter, writer); } - } - // Zip up any jars, if necessary. - DataEntryWriter jarWriter = new JarWriter(writer); - if (outputIsJar) - { - // Always zip. - writer = jarWriter; - } - else - { - // Only zip up jars. - writer = new FilteredDataEntryWriter(new DataEntryParentFilter( - new DataEntryNameFilter( - new ExtensionMatcher(".jar"))), - jarWriter, - writer); - } + // Zip up any aars, if necessary. + DataEntryWriter aarWriter = new JarWriter(writer); + if (outputIsAar) + { + // Always zip. + writer = aarWriter; + } + else + { + // Only zip up aars. + writer = new FilteredDataEntryWriter(new DataEntryParentFilter( + new DataEntryNameFilter( + new ExtensionMatcher(".aar"))), + aarWriter, + writer); + } + + // Zip up any jars, if necessary. + DataEntryWriter jarWriter = new JarWriter(writer); + if (outputIsJar) + { + // Always zip. + writer = jarWriter; + } + else + { + // Only zip up jars. + writer = new FilteredDataEntryWriter(new DataEntryParentFilter( + new DataEntryNameFilter( + new ExtensionMatcher(".jar"))), + jarWriter, + writer); + } + + // Zip up any apks, if necessary. + DataEntryWriter apkWriter = new JarWriter(writer); + if (outputIsApk) + { + // Always zip. + writer = apkWriter; + } + else + { + // Only zip up apks. + writer = new FilteredDataEntryWriter(new DataEntryParentFilter( + new DataEntryNameFilter( + new ExtensionMatcher(".apk"))), + apkWriter, + writer); + } // Create the copying DataEntryReader. DataEntryReader reader = new DataEntryCopier(writer); - + boolean inputIsApk = input.endsWith(".apk") || + input.endsWith(".ap_"); boolean inputIsJar = input.endsWith(".jar"); + boolean inputIsAar = input.endsWith(".aar"); boolean inputIsWar = input.endsWith(".war"); + boolean inputIsEar = input.endsWith(".ear"); boolean inputIsZip = input.endsWith(".zip"); - // Unzip any jars, if necessary. - DataEntryReader jarReader = new JarReader(reader); - if (inputIsJar) + // Unzip any apks, if necessary. + DataEntryReader apkReader = new JarReader(reader); + if (inputIsApk) { // Always unzip. - reader = jarReader; + reader = apkReader; } else { - // Only unzip jar entries. + // Only unzip apk entries. reader = new FilteredDataEntryReader(new DataEntryNameFilter( - new ExtensionMatcher(".jar")), - jarReader, + new ExtensionMatcher(".apk")), + apkReader, reader); - // Unzip any wars, if necessary. - DataEntryReader warReader = new JarReader(reader); - if (inputIsWar) + // Unzip any jars, if necessary. + DataEntryReader jarReader = new JarReader(reader); + if (inputIsJar) { // Always unzip. - reader = warReader; + reader = jarReader; } else { - // Only unzip war entries. + // Only unzip jar entries. reader = new FilteredDataEntryReader(new DataEntryNameFilter( - new ExtensionMatcher(".war")), - warReader, + new ExtensionMatcher(".jar")), + jarReader, reader); - } - // Unzip any zips, if necessary. - DataEntryReader zipReader = new JarReader(reader); - if (inputIsZip) - { - // Always unzip. - reader = zipReader; - } - else - { - // Only unzip zip entries. - reader = new FilteredDataEntryReader(new DataEntryNameFilter( - new ExtensionMatcher(".zip")), - zipReader, - reader); + // Unzip any aars, if necessary. + DataEntryReader aarReader = new JarReader(reader); + if (inputIsAar) + { + // Always unzip. + reader = aarReader; + } + else + { + // Only unzip aar entries. + reader = new FilteredDataEntryReader(new DataEntryNameFilter( + new ExtensionMatcher(".aar")), + aarReader, + reader); + + // Unzip any wars, if necessary. + DataEntryReader warReader = new JarReader(reader); + if (inputIsWar) + { + // Always unzip. + reader = warReader; + } + else + { + // Only unzip war entries. + reader = new FilteredDataEntryReader(new DataEntryNameFilter( + new ExtensionMatcher(".war")), + warReader, + reader); + + // Unzip any ears, if necessary. + DataEntryReader earReader = new JarReader(reader); + if (inputIsEar) + { + // Always unzip. + reader = earReader; + } + else + { + // Only unzip ear entries. + reader = new FilteredDataEntryReader(new DataEntryNameFilter( + new ExtensionMatcher(".ear")), + earReader, + reader); + + // Unzip any zips, if necessary. + DataEntryReader zipReader = new JarReader(reader); + if (inputIsZip) + { + // Always unzip. + reader = zipReader; + } + else + { + // Only unzip zip entries. + reader = new FilteredDataEntryReader(new DataEntryNameFilter( + new ExtensionMatcher(".zip")), + zipReader, + reader); + } + } + } + } } } diff --git a/src/proguard/io/DataEntryDirectoryFilter.java b/src/proguard/io/DataEntryDirectoryFilter.java index 5bf46bb..a9b2c8b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +20,6 @@ */ package proguard.io; -import proguard.util.StringMatcher; - /** * This DataEntryFilter filters data entries based on whether they represent * directories. diff --git a/src/proguard/io/DataEntryFilter.java b/src/proguard/io/DataEntryFilter.java index b8b6b20..0b604ba 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 5aebcdd..bc676c0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 c5742e9..aabb0e8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 DataEntryObfuscator implements DataEntryReader String className = dataEntryName.substring(0, suffixIndex); // Did we get to the package separator? - if (c == ClassConstants.INTERNAL_PACKAGE_SEPARATOR) + if (c == ClassConstants.PACKAGE_SEPARATOR) { break; } diff --git a/src/proguard/io/DataEntryParentFilter.java b/src/proguard/io/DataEntryParentFilter.java index 1cc1997..1d4d1e4 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 ddf946b..6cdaef3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 39dc82d..d03124a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 99600ae..c8bb319 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -81,7 +81,7 @@ public class DataEntryRenamer implements DataEntryReader if (dataEntry.isDirectory() && name.length() > 0) { - name += ClassConstants.INTERNAL_PACKAGE_SEPARATOR; + name += ClassConstants.PACKAGE_SEPARATOR; } String newName = (String)nameMap.get(name); diff --git a/src/proguard/io/DataEntryRewriter.java b/src/proguard/io/DataEntryRewriter.java index ec07767..666aa0d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -124,7 +124,7 @@ public class DataEntryRewriter extends DataEntryCopier // Replace dots by forward slashes. String className = containsDots ? - word.replace('.', ClassConstants.INTERNAL_PACKAGE_SEPARATOR) : + word.replace('.', ClassConstants.PACKAGE_SEPARATOR) : word; // Find the class corrsponding to the word. @@ -137,7 +137,7 @@ public class DataEntryRewriter extends DataEntryCopier { // Replace forward slashes by dots. newWord = containsDots ? - newClassName.replace(ClassConstants.INTERNAL_PACKAGE_SEPARATOR, '.') : + newClassName.replace(ClassConstants.PACKAGE_SEPARATOR, '.') : newClassName; } } diff --git a/src/proguard/io/DataEntryWriter.java b/src/proguard/io/DataEntryWriter.java index 871f823..5dac1e3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 72e2e6d..ebdf4c4 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,12 +20,6 @@ */ package proguard.io; -import proguard.classfile.ClassConstants; -import proguard.util.ExtensionMatcher; - -import java.io.IOException; - - /** * This DataEntryReader delegates to one of two other DataEntryReader instances, * depending on whether the data entry represents a directory or not. diff --git a/src/proguard/io/DirectoryPump.java b/src/proguard/io/DirectoryPump.java index cd6c2ab..fe387ca 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 7948ee2..e44e195 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +137,7 @@ public class DirectoryWriter implements DataEntryWriter return isFile ? baseFile : new File(baseFile, - dataEntry.getName().replace(ClassConstants.INTERNAL_PACKAGE_SEPARATOR, + dataEntry.getName().replace(ClassConstants.PACKAGE_SEPARATOR, File.separatorChar)); } diff --git a/src/proguard/io/FileDataEntry.java b/src/proguard/io/FileDataEntry.java index 618a092..f188f3b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 @@ public class FileDataEntry implements DataEntry { private final File directory; private final File file; - private InputStream inputStream; + private InputStream inputStream; public FileDataEntry(File directory, @@ -53,7 +53,7 @@ public class FileDataEntry implements DataEntry file.getName() : file.getPath() .substring(directory.getPath().length() + File.separator.length()) - .replace(File.separatorChar, ClassConstants.INTERNAL_PACKAGE_SEPARATOR); + .replace(File.separatorChar, ClassConstants.PACKAGE_SEPARATOR); } diff --git a/src/proguard/io/FilteredDataEntryReader.java b/src/proguard/io/FilteredDataEntryReader.java index 03b5dd8..ce0f207 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 b3b751c..b8d7977 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 7d5f93f..74da6f8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 be4c97b..c4b7e3f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 d85e63b..5437f28 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ import java.util.*; import java.util.jar.*; import java.util.zip.*; - /** * This DataEntryWriter sends data entries to a given jar/zip file. * The manifest and comment properties can optionally be set. @@ -75,7 +74,7 @@ public class JarWriter implements DataEntryWriter, Finisher public boolean createDirectory(DataEntry dataEntry) throws IOException { - //Make sure we can start with a new entry. + // Make sure we can start with a new entry. if (!prepareEntry(dataEntry)) { return false; @@ -85,7 +84,7 @@ public class JarWriter implements DataEntryWriter, Finisher closeEntry(); // Get the directory entry name. - String name = dataEntry.getName() + ClassConstants.INTERNAL_PACKAGE_SEPARATOR; + String name = dataEntry.getName() + ClassConstants.PACKAGE_SEPARATOR; // We have to check if the name is already used, because // ZipOutputStream doesn't handle this case properly (it throws @@ -182,7 +181,7 @@ public class JarWriter implements DataEntryWriter, Finisher */ private boolean prepareEntry(DataEntry dataEntry) throws IOException { - // Get the parent stream, new or exisiting. + // Get the parent stream, new or existing. // This may finish our own jar output stream. OutputStream parentOutputStream = dataEntryWriter.getOutputStream(dataEntry.getParent(), this); diff --git a/src/proguard/io/ManifestRewriter.java b/src/proguard/io/ManifestRewriter.java index 8a8c7ae..f45ad9e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.io; -import proguard.classfile.*; +import proguard.classfile.ClassPool; import java.io.*; diff --git a/src/proguard/io/NameFilter.java b/src/proguard/io/NameFilter.java index 67d630e..b2e5539 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 f24ef37..9f97e46 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 a0f5657..ce97b3f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 20a9d3b..84e24db 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 +35,7 @@ public class ZipDataEntry implements DataEntry private final DataEntry parent; private final ZipEntry zipEntry; private ZipInputStream zipInputStream; + private InputStream bufferedInputStream; public ZipDataEntry(DataEntry parent, @@ -53,12 +54,12 @@ public class ZipDataEntry implements DataEntry { // Get the right separators. String name = zipEntry.getName() - .replace(File.separatorChar, ClassConstants.INTERNAL_PACKAGE_SEPARATOR); + .replace(File.separatorChar, ClassConstants.PACKAGE_SEPARATOR); // Chop the trailing directory slash, if any. int length = name.length(); return length > 0 && - name.charAt(length-1) == ClassConstants.INTERNAL_PACKAGE_SEPARATOR ? + name.charAt(length-1) == ClassConstants.PACKAGE_SEPARATOR ? name.substring(0, length -1) : name; } @@ -72,14 +73,20 @@ public class ZipDataEntry implements DataEntry public InputStream getInputStream() throws IOException { - return zipInputStream; + if (bufferedInputStream == null) + { + bufferedInputStream = new BufferedInputStream(zipInputStream); + } + + return bufferedInputStream; } public void closeInputStream() throws IOException { zipInputStream.closeEntry(); - zipInputStream = null; + zipInputStream = null; + bufferedInputStream = null; } diff --git a/src/proguard/obfuscate/AttributeShrinker.java b/src/proguard/obfuscate/AttributeShrinker.java index 0c3ab94..b1b6dd3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/obfuscate/AttributeUsageMarker.java b/src/proguard/obfuscate/AttributeUsageMarker.java index 32a512b..81a4554 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/obfuscate/ClassObfuscator.java b/src/proguard/obfuscate/ClassObfuscator.java index 9e1a91c..516c889 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,14 +109,14 @@ implements ClassVisitor, if (flattenPackageHierarchy != null && flattenPackageHierarchy.length() > 0) { - flattenPackageHierarchy += ClassConstants.INTERNAL_PACKAGE_SEPARATOR; + flattenPackageHierarchy += ClassConstants.PACKAGE_SEPARATOR; } // First append the package separator if necessary. if (repackageClasses != null && repackageClasses.length() > 0) { - repackageClasses += ClassConstants.INTERNAL_PACKAGE_SEPARATOR; + repackageClasses += ClassConstants.PACKAGE_SEPARATOR; } this.useMixedCaseClassNames = useMixedCaseClassNames; @@ -151,7 +151,7 @@ implements ClassVisitor, // the an outer class prefix, if any, or it may be the fixed base // package, if classes are to be repackaged. String newPackagePrefix = newClassName != null ? - newClassName + ClassConstants.INTERNAL_INNER_CLASS_SEPARATOR : + newClassName + ClassConstants.INNER_CLASS_SEPARATOR : newPackagePrefix(ClassUtil.internalPackagePrefix(programClass.getName())); // Come up with a new class name, numeric or ordinary. @@ -410,7 +410,7 @@ implements ClassVisitor, // Let the factory produce a package name. newPackagePrefix = newSuperPackagePrefix + packageNameFactory.nextName() + - ClassConstants.INTERNAL_PACKAGE_SEPARATOR; + ClassConstants.PACKAGE_SEPARATOR; } while (packagePrefixMap.containsValue(newPackagePrefix)); diff --git a/src/proguard/obfuscate/ClassRenamer.java b/src/proguard/obfuscate/ClassRenamer.java index 4c5e496..0a0974d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 4a7e28c..ffe6e41 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 d11f443..365ec15 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.obfuscate; -import proguard.classfile.*; +import proguard.classfile.Clazz; import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.ClassVisitor; diff --git a/src/proguard/obfuscate/MappingKeeper.java b/src/proguard/obfuscate/MappingKeeper.java index 7ab1e25..e955e53 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -163,7 +163,7 @@ public class MappingKeeper implements MappingProcessor warningPrinter.print(ClassUtil.internalClassName(className), "Warning: " + className + - ": method '" + methodReturnType + " " + methodName + ClassConstants.EXTERNAL_METHOD_ARGUMENTS_OPEN + methodArguments + ClassConstants.EXTERNAL_METHOD_ARGUMENTS_CLOSE + + ": method '" + methodReturnType + " " + methodName + JavaConstants.METHOD_ARGUMENTS_OPEN + methodArguments + JavaConstants.METHOD_ARGUMENTS_CLOSE + "' is not being kept as '" + currentNewName + "', but remapped to '" + newMethodName + "'"); } diff --git a/src/proguard/obfuscate/MappingPrinter.java b/src/proguard/obfuscate/MappingPrinter.java index a28d10c..aab779f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +106,7 @@ implements ClassVisitor, // Special cases: <clinit> and <init> are always kept unchanged. // We can ignore them here. String name = programMethod.getName(programClass); - if (name.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) || - name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + if (ClassUtil.isInitializer(name)) { return; } diff --git a/src/proguard/obfuscate/MappingProcessor.java b/src/proguard/obfuscate/MappingProcessor.java index 92a916a..8047e8d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 51d14ac..88a13e0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 5205fee..5b7e16f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 1544901..bab9e95 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.obfuscate; import proguard.classfile.*; -import proguard.classfile.util.SimplifiedVisitor; +import proguard.classfile.util.*; import proguard.classfile.visitor.MemberVisitor; import java.util.Map; @@ -64,8 +64,7 @@ implements MemberVisitor // Special cases: <clinit> and <init> are always kept unchanged. // We can ignore them here. String name = member.getName(clazz); - if (name.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) || - name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + if (ClassUtil.isInitializer(name)) { return; } diff --git a/src/proguard/obfuscate/MemberNameConflictFixer.java b/src/proguard/obfuscate/MemberNameConflictFixer.java index 68e7c05..00ac6f7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -81,8 +81,7 @@ public class MemberNameConflictFixer implements MemberVisitor // Special cases: <clinit> and <init> are always kept unchanged. // We can ignore them here. String name = programMethod.getName(programClass); - if (name.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) || - name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + if (ClassUtil.isInitializer(name)) { return; } diff --git a/src/proguard/obfuscate/MemberNameFilter.java b/src/proguard/obfuscate/MemberNameFilter.java index 6d95270..dfff99a 100644 --- a/src/proguard/obfuscate/MemberNameFilter.java +++ b/src/proguard/obfuscate/MemberNameFilter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +106,7 @@ public class MemberNameFilter implements MemberVisitor return hasName(method) || (hasName(clazz) && - method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)); + method.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT)); } diff --git a/src/proguard/obfuscate/MemberObfuscator.java b/src/proguard/obfuscate/MemberObfuscator.java index adf590c..b5211ac 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -72,8 +72,7 @@ implements MemberVisitor // Special cases: <clinit> and <init> are always kept unchanged. // We can ignore them here. String name = member.getName(clazz); - if (name.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) || - name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + if (ClassUtil.isInitializer(name)) { return; } diff --git a/src/proguard/obfuscate/MemberSpecialNameFilter.java b/src/proguard/obfuscate/MemberSpecialNameFilter.java index 0eb4d2d..f8ab913 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/obfuscate/MultiMappingProcessor.java b/src/proguard/obfuscate/MultiMappingProcessor.java index 051260f..e10c100 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/obfuscate/NameFactory.java b/src/proguard/obfuscate/NameFactory.java index 97ebe5a..cb5f998 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 b04d12e..a6188a6 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 5283ef3..376943f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,11 +21,11 @@ package proguard.obfuscate; import proguard.classfile.*; -import proguard.classfile.util.SimplifiedVisitor; -import proguard.classfile.constant.ClassConstant; -import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.attribute.*; import proguard.classfile.attribute.visitor.*; +import proguard.classfile.constant.ClassConstant; +import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.util.*; import proguard.classfile.visitor.*; @@ -156,11 +156,9 @@ implements ClassVisitor, { String name = method.getName(clazz); - if (!name.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) && - !name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + if (!ClassUtil.isInitializer(name)) { - MemberObfuscator.setFixedNewMemberName(method, - method.getName(clazz)); + MemberObfuscator.setFixedNewMemberName(method, name); } } } diff --git a/src/proguard/obfuscate/NumericNameFactory.java b/src/proguard/obfuscate/NumericNameFactory.java index b1e38b1..0a23f16 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,9 +20,6 @@ */ package proguard.obfuscate; -import java.util.*; - - /** * This <code>NameFactory</code> generates unique numeric names, starting at * "1". diff --git a/src/proguard/obfuscate/Obfuscator.java b/src/proguard/obfuscate/Obfuscator.java index cc79b0d..b2758a7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -98,6 +98,16 @@ public class Obfuscator libraryClassPool.classesAccept(nameMarker); libraryClassPool.classesAccept(new AllMemberVisitor(nameMarker)); + // We also keep the names of all methods of classes that are returned + // by dynamic method invocations. They may return dynamic + // implementations of interfaces. The method names then have to match + // with the invoke dynamic names. + programClassPool.classesAccept( + new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_7, + new AllConstantVisitor( + new DynamicReturnedClassVisitor( + new AllMemberVisitor(nameMarker))))); + // Mark attributes that have to be kept. AttributeVisitor attributeUsageMarker = new NonEmptyAttributeFilter( @@ -105,7 +115,7 @@ public class Obfuscator AttributeVisitor optionalAttributeUsageMarker = configuration.keepAttributes == null ? null : - new AttributeNameFilter(new ListParser(new NameParser()).parse(configuration.keepAttributes), + new AttributeNameFilter(configuration.keepAttributes, attributeUsageMarker); programClassPool.classesAccept( @@ -227,20 +237,20 @@ public class Obfuscator // the hierarchy. new ClassHierarchyTraveler(true, false, false, true, new AllMemberVisitor( - new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0, + new MemberAccessFilter(ClassConstants.ACC_PRIVATE, 0, new MemberNameCollector(configuration.overloadAggressively, descriptorMap)))), // Collect all non-private member names anywhere in the hierarchy. new ClassHierarchyTraveler(true, true, true, true, new AllMemberVisitor( - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, new MemberNameCollector(configuration.overloadAggressively, descriptorMap)))), // Assign new names to all non-private members in this class. new AllMemberVisitor( - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, new MemberObfuscator(configuration.overloadAggressively, nameFactory, descriptorMap))), @@ -261,7 +271,7 @@ public class Obfuscator // Collect all non-private member names higher up the hierarchy. new ClassHierarchyTraveler(false, true, true, false, new AllMemberVisitor( - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, new MemberNameCollector(configuration.overloadAggressively, descriptorMap)))), @@ -272,7 +282,7 @@ public class Obfuscator // 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 ClassAccessFilter(ClassConstants.ACC_ABSTRACT, 0, new ClassHierarchyTraveler(false, false, true, false, new AllMemberVisitor( new MemberNameCollector(configuration.overloadAggressively, @@ -280,7 +290,7 @@ public class Obfuscator // Assign new names to all private members in this class. new AllMemberVisitor( - new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0, + new MemberAccessFilter(ClassConstants.ACC_PRIVATE, 0, new MemberObfuscator(configuration.overloadAggressively, nameFactory, descriptorMap))), @@ -319,7 +329,7 @@ public class Obfuscator // the hierarchy. new ClassHierarchyTraveler(true, false, false, true, new AllMemberVisitor( - new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0, + new MemberAccessFilter(ClassConstants.ACC_PRIVATE, 0, new MemberNameCollector(configuration.overloadAggressively, descriptorMap)))), @@ -327,7 +337,7 @@ public class Obfuscator // higher up the hierarchy. new ClassHierarchyTraveler(true, true, true, false, new AllMemberVisitor( - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, new MemberNameCollector(configuration.overloadAggressively, descriptorMap)))), @@ -335,7 +345,7 @@ public class Obfuscator // in this class and higher up the hierarchy. new ClassHierarchyTraveler(true, true, true, false, new AllMemberVisitor( - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, new MemberNameConflictFixer(configuration.overloadAggressively, descriptorMap, warningPrinter, @@ -360,14 +370,14 @@ public class Obfuscator // Collect all non-private member names higher up the hierarchy. new ClassHierarchyTraveler(false, true, true, false, new AllMemberVisitor( - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, new MemberNameCollector(configuration.overloadAggressively, descriptorMap)))), // Assign new names to all conflicting private members in this // class. new AllMemberVisitor( - new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0, + new MemberAccessFilter(ClassConstants.ACC_PRIVATE, 0, new MemberNameConflictFixer(configuration.overloadAggressively, descriptorMap, warningPrinter, @@ -391,12 +401,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)"); + System.err.println(" (http://proguard.sourceforge.net/manual/troubleshooting.html#mappingconflict2)"); - if (!configuration.ignoreWarnings) - { + if (!configuration.ignoreWarnings) + { throw new IOException("Please correct the above warnings first."); } } @@ -438,8 +448,7 @@ public class Obfuscator configuration.allowAccessModification) { programClassPool.classesAccept( - new AllConstantVisitor( - new AccessFixer())); + new AccessFixer()); // Fix the access flags of the inner classes information. programClassPool.classesAccept( diff --git a/src/proguard/obfuscate/ParameterNameMarker.java b/src/proguard/obfuscate/ParameterNameMarker.java index 22af125..fbe8a81 100644 --- a/src/proguard/obfuscate/ParameterNameMarker.java +++ b/src/proguard/obfuscate/ParameterNameMarker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.obfuscate; import proguard.classfile.*; import proguard.classfile.attribute.*; import proguard.classfile.attribute.visitor.AttributeVisitor; -import proguard.classfile.util.*; +import proguard.classfile.util.SimplifiedVisitor; /** * This AttributeVisitor trims and marks all local variable (type) table @@ -60,9 +60,9 @@ implements AttributeVisitor if (!AttributeUsageMarker.isUsed(localVariableTableAttribute) && hasParameters(clazz, method)) { - // Shift the entries that start at offset 0 to the front. + // Shift the entries that start at offset 0 to the front. int newIndex = 0; - + for (int index = 0; index < localVariableTableAttribute.u2localVariableTableLength; index++) { LocalVariableInfo localVariableInfo = @@ -92,9 +92,9 @@ implements AttributeVisitor if (!AttributeUsageMarker.isUsed(localVariableTypeTableAttribute) && hasParameters(clazz, method)) { - // Shift the entries that start at offset 0 to the front. + // Shift the entries that start at offset 0 to the front. int newIndex = 0; - + for (int index = 0; index < localVariableTypeTableAttribute.u2localVariableTypeTableLength; index++) { LocalVariableTypeInfo localVariableTypeInfo = @@ -109,7 +109,7 @@ implements AttributeVisitor // Trim the table. localVariableTypeTableAttribute.u2localVariableTypeTableLength = newIndex; - + // Mark the table if there are any entries. if (newIndex > 0) { @@ -123,6 +123,6 @@ implements AttributeVisitor private boolean hasParameters(Clazz clazz, Method method) { - return method.getDescriptor(clazz).charAt(1) != ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE; + return method.getDescriptor(clazz).charAt(1) != ClassConstants.METHOD_ARGUMENTS_CLOSE; } }
\ No newline at end of file diff --git a/src/proguard/obfuscate/SimpleNameFactory.java b/src/proguard/obfuscate/SimpleNameFactory.java index 0473852..c7e1a50 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 248d18f..57ab009 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 596f919..84bb55f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/BootstrapMethodArgumentShrinker.java b/src/proguard/optimize/BootstrapMethodArgumentShrinker.java index 26f1349..b4ac4cc 100644 --- a/src/proguard/optimize/BootstrapMethodArgumentShrinker.java +++ b/src/proguard/optimize/BootstrapMethodArgumentShrinker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,13 +21,11 @@ package proguard.optimize; import proguard.classfile.*; -import proguard.classfile.attribute.*; -import proguard.classfile.attribute.annotation.*; -import proguard.classfile.attribute.visitor.*; +import proguard.classfile.attribute.BootstrapMethodInfo; +import proguard.classfile.attribute.visitor.BootstrapMethodInfoVisitor; import proguard.classfile.constant.*; import proguard.classfile.constant.visitor.ConstantVisitor; -import proguard.classfile.editor.ConstantPoolEditor; -import proguard.classfile.util.*; +import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.MemberVisitor; import proguard.optimize.info.*; import proguard.optimize.peephole.VariableShrinker; @@ -96,6 +94,9 @@ implements BootstrapMethodInfoVisitor, // Implementations for MemberVisitor. + public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) {} + + 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 668d43d..261e164 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ implements AttributeVisitor // Implementations for AttributeVisitor. - public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) { attributeVisitor.visitUnknownAttribute(clazz, unknownAttribute); @@ -144,6 +143,12 @@ implements AttributeVisitor } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute exceptionsAttribute) + { + attributeVisitor.visitMethodParametersAttribute(clazz, method, exceptionsAttribute); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { attributeVisitor.visitExceptionsAttribute(clazz, method, exceptionsAttribute); @@ -228,6 +233,54 @@ implements AttributeVisitor } + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, runtimeVisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, field, runtimeVisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, runtimeVisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) + { + attributeVisitor.visitRuntimeVisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeVisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, runtimeInvisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Field field, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, field, runtimeInvisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, runtimeInvisibleTypeAnnotationsAttribute); + } + + + public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) + { + attributeVisitor.visitRuntimeInvisibleTypeAnnotationsAttribute(clazz, method, codeAttribute, runtimeInvisibleTypeAnnotationsAttribute); + } + + public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) { attributeVisitor.visitAnnotationDefaultAttribute(clazz, method, annotationDefaultAttribute); diff --git a/src/proguard/optimize/ConstantMemberFilter.java b/src/proguard/optimize/ConstantMemberFilter.java index 1f30a30..6bd8619 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 1500fd0..8a5058e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ import proguard.classfile.util.*; import proguard.classfile.visitor.MemberVisitor; import proguard.evaluation.value.Value; import proguard.optimize.evaluation.StoringInvocationUnit; -import proguard.optimize.info.ParameterUsageMarker; /** * This <code>MemberVisitor</code> delegates its visits to program methods @@ -60,7 +59,7 @@ implements MemberVisitor // All parameters of non-static methods are shifted by one in the local // variable frame. int firstParameterIndex = - (programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? + (programMethod.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ? 0 : 1; int parameterCount = diff --git a/src/proguard/optimize/DuplicateInitializerFixer.java b/src/proguard/optimize/DuplicateInitializerFixer.java index 95bc2f1..f5d5787 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +21,9 @@ package proguard.optimize; import proguard.classfile.*; -import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.attribute.*; import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.editor.ConstantPoolEditor; import proguard.classfile.util.*; import proguard.classfile.visitor.MemberVisitor; @@ -41,11 +41,11 @@ implements MemberVisitor, private static final char[] TYPES = new char[] { - ClassConstants.INTERNAL_TYPE_BYTE, - ClassConstants.INTERNAL_TYPE_CHAR, - ClassConstants.INTERNAL_TYPE_SHORT, - ClassConstants.INTERNAL_TYPE_INT, - ClassConstants.INTERNAL_TYPE_BOOLEAN + ClassConstants.TYPE_BYTE, + ClassConstants.TYPE_CHAR, + ClassConstants.TYPE_SHORT, + ClassConstants.TYPE_INT, + ClassConstants.TYPE_BOOLEAN }; @@ -78,7 +78,7 @@ implements MemberVisitor, { // Is it a class instance initializer? String name = programMethod.getName(programClass); - if (name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + if (name.equals(ClassConstants.METHOD_NAME_INIT)) { // Is there already another initializer with the same descriptor? String descriptor = programMethod.getDescriptor(programClass); @@ -92,7 +92,7 @@ implements MemberVisitor, programMethod = (ProgramMethod)similarMethod; } - int index = descriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE); + int index = descriptor.indexOf(ClassConstants.METHOD_ARGUMENTS_CLOSE); // Try to find a new, unique descriptor. int typeCounter = 0; @@ -105,7 +105,7 @@ implements MemberVisitor, for (int arrayDimension = 0; arrayDimension < typeCounter / TYPES.length; arrayDimension++) { - newDescriptorBuffer.append(ClassConstants.INTERNAL_TYPE_ARRAY); + newDescriptorBuffer.append(ClassConstants.TYPE_ARRAY); } newDescriptorBuffer.append(TYPES[typeCounter % TYPES.length]); @@ -171,9 +171,9 @@ implements MemberVisitor, public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute) { String descriptor = method.getDescriptor(clazz); - int descriptorIndex = descriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE); - String signature = clazz.getString(signatureAttribute.u2signatureIndex); - int signatureIndex = signature.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE); + int descriptorIndex = descriptor.indexOf(ClassConstants.METHOD_ARGUMENTS_CLOSE); + String signature = signatureAttribute.getSignature(clazz); + int signatureIndex = signature.indexOf(ClassConstants.METHOD_ARGUMENTS_CLOSE); String newSignature = signature.substring(0, signatureIndex) + descriptor.charAt(descriptorIndex - 1) + @@ -188,13 +188,13 @@ implements MemberVisitor, public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) { // Update the number of parameters. - int oldParametersCount = parameterAnnotationsAttribute.u2parametersCount++; + int oldParametersCount = parameterAnnotationsAttribute.u1parametersCount++; if (parameterAnnotationsAttribute.u2parameterAnnotationsCount == null || - parameterAnnotationsAttribute.u2parameterAnnotationsCount.length < parameterAnnotationsAttribute.u2parametersCount) + parameterAnnotationsAttribute.u2parameterAnnotationsCount.length < parameterAnnotationsAttribute.u1parametersCount) { - int[] annotationsCounts = new int[parameterAnnotationsAttribute.u2parametersCount]; - Annotation[][] annotations = new Annotation[parameterAnnotationsAttribute.u2parametersCount][]; + int[] annotationsCounts = new int[parameterAnnotationsAttribute.u1parametersCount]; + Annotation[][] annotations = new Annotation[parameterAnnotationsAttribute.u1parametersCount][]; System.arraycopy(parameterAnnotationsAttribute.u2parameterAnnotationsCount, 0, diff --git a/src/proguard/optimize/DuplicateInitializerInvocationFixer.java b/src/proguard/optimize/DuplicateInitializerInvocationFixer.java index 5edaba0..22bfc52 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -131,11 +131,15 @@ implements AttributeVisitor, // Implementations for ConstantVisitor. - public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) + public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant) { // Check the referenced constructor descriptor. - descriptor = methodrefConstant.getType(clazz); - methodrefConstant.referencedMemberAccept(this); + if (refConstant.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT)) + { + descriptor = refConstant.getType(clazz); + + refConstant.referencedMemberAccept(this); + } } diff --git a/src/proguard/optimize/KeepMarker.java b/src/proguard/optimize/KeepMarker.java index b0eab7b..c98ca6e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/optimize/KeptClassFilter.java b/src/proguard/optimize/KeptClassFilter.java index 60a9d3e..c4e436f 100644 --- a/src/proguard/optimize/KeptClassFilter.java +++ b/src/proguard/optimize/KeptClassFilter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/KeptMemberFilter.java b/src/proguard/optimize/KeptMemberFilter.java index 1bdadb4..279c019 100644 --- a/src/proguard/optimize/KeptMemberFilter.java +++ b/src/proguard/optimize/KeptMemberFilter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/optimize/MemberDescriptorSpecializer.java b/src/proguard/optimize/MemberDescriptorSpecializer.java index 4dce62e..4656092 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +99,7 @@ implements MemberVisitor // All parameters of non-static methods are shifted by one in the local // variable frame. int firstParameterIndex = - (programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? + (programMethod.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ? 0 : 1; int parameterCount = diff --git a/src/proguard/optimize/MethodDescriptorShrinker.java b/src/proguard/optimize/MethodDescriptorShrinker.java index d8d4425..f5f52b0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,13 +23,15 @@ package proguard.optimize; import proguard.classfile.*; import proguard.classfile.attribute.*; import proguard.classfile.attribute.annotation.*; -import proguard.classfile.attribute.visitor.*; +import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.editor.ConstantPoolEditor; import proguard.classfile.util.*; import proguard.classfile.visitor.MemberVisitor; import proguard.optimize.info.*; import proguard.optimize.peephole.VariableShrinker; +import java.util.Arrays; + /** * This MemberVisitor removes unused parameters in the descriptors of the * methods that it visits. @@ -74,32 +76,26 @@ implements MemberVisitor, public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { + if (DEBUG) + { + System.out.println("MethodDescriptorShrinker: ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"]"); + } + // Update the descriptor if it has any unused parameters. String descriptor = programMethod.getDescriptor(programClass); String newDescriptor = shrinkDescriptor(programMethod, descriptor); - if (!descriptor.equals(newDescriptor)) + if (!newDescriptor.equals(descriptor)) { - // Shrink the signature and parameter annotations. - programMethod.attributesAccept(programClass, this); - String name = programMethod.getName(programClass); String newName = name; // Append a code, if the method isn't a class instance initializer. - if (!name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + if (!name.equals(ClassConstants.METHOD_NAME_INIT)) { newName += ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode())); } - if (DEBUG) - { - System.out.println("MethodDescriptorShrinker:"); - System.out.println(" ["+programClass.getName()+"."+ - name+descriptor+"] -> ["+ - newName+newDescriptor+"]"); - } - ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor(programClass); @@ -120,6 +116,14 @@ implements MemberVisitor, programMethod.u2descriptorIndex = constantPoolEditor.addUtf8Constant(newDescriptor); + if (DEBUG) + { + System.out.println(" -> ["+newName+newDescriptor+"]"); + } + + // Shrink the signature and parameter annotations. + programMethod.attributesAccept(programClass, this); + // Visit the method, if required. if (extraMemberVisitor != null) { @@ -136,19 +140,32 @@ implements MemberVisitor, public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute) { + if (DEBUG) + { + System.out.println(" ["+signatureAttribute.getSignature(clazz)+"]"); + } + // Compute the new signature. - String signature = clazz.getString(signatureAttribute.u2signatureIndex); + String signature = signatureAttribute.getSignature(clazz); String newSignature = shrinkDescriptor(method, signature); - // Update the signature. - signatureAttribute.u2signatureIndex = - new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature); + if (!newSignature.equals(signature)) + { + // Update the signature. + signatureAttribute.u2signatureIndex = + new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature); - // Update the referenced classes. - signatureAttribute.referencedClasses = - shrinkReferencedClasses(method, - signature, - signatureAttribute.referencedClasses); + // Update the referenced classes. + signatureAttribute.referencedClasses = + shrinkReferencedClasses(method, + signature, + signatureAttribute.referencedClasses); + + if (DEBUG) + { + System.out.println(" -> ["+newSignature+"]"); + } + } } @@ -160,7 +177,7 @@ implements MemberVisitor, // All parameters of non-static methods are shifted by one in the local // variable frame. int parameterIndex = - (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? + (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ? 0 : 1; int annotationIndex = 0; @@ -186,7 +203,7 @@ implements MemberVisitor, } // Update the number of parameters. - parameterAnnotationsAttribute.u2parametersCount = newAnnotationIndex; + parameterAnnotationsAttribute.u1parametersCount = newAnnotationIndex; // Clear the unused entries. while (newAnnotationIndex < annotationIndex) @@ -207,18 +224,20 @@ implements MemberVisitor, // All parameters of non-static methods are shifted by one in the local // variable frame. int parameterIndex = - (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? + (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ? 0 : 1; - // Go over the parameters. InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(descriptor); - StringBuffer newDescriptorBuffer = new StringBuffer(); + StringBuffer newDescriptorBuffer = + new StringBuffer(descriptor.length()); + // Copy the formal type parameters. newDescriptorBuffer.append(internalTypeEnumeration.formalTypeParameters()); - newDescriptorBuffer.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN); + newDescriptorBuffer.append(ClassConstants.METHOD_ARGUMENTS_OPEN); + // Go over the parameters. while (internalTypeEnumeration.hasMoreTypes()) { String type = internalTypeEnumeration.nextType(); @@ -234,7 +253,8 @@ implements MemberVisitor, parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1; } - newDescriptorBuffer.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE); + // Copy the return type. + newDescriptorBuffer.append(ClassConstants.METHOD_ARGUMENTS_CLOSE); newDescriptorBuffer.append(internalTypeEnumeration.returnType()); return newDescriptorBuffer.toString(); @@ -253,30 +273,32 @@ implements MemberVisitor, // All parameters of non-static methods are shifted by one in the local // variable frame. int parameterIndex = - (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? + (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 ? 0 : 1; - int referencedClassIndex = 0; - int newReferencedClassIndex = 0; - - // Go over the parameters. InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(descriptor); - // Also look at the formal type parameters. - String type = internalTypeEnumeration.formalTypeParameters(); - int count = new DescriptorClassEnumeration(type).classCount(); - for (int counter = 0; counter < count; counter++) + int referencedClassIndex = 0; + int newReferencedClassIndex = 0; + + // Copy the formal type parameters. { - referencedClasses[newReferencedClassIndex++] = - referencedClasses[referencedClassIndex++]; + String type = internalTypeEnumeration.formalTypeParameters(); + int count = new DescriptorClassEnumeration(type).classCount(); + for (int counter = 0; counter < count; counter++) + { + referencedClasses[newReferencedClassIndex++] = + referencedClasses[referencedClassIndex++]; + } } + // Go over the parameters. while (internalTypeEnumeration.hasMoreTypes()) { // Consider the classes referenced by this parameter type. - type = internalTypeEnumeration.nextType(); - count = new DescriptorClassEnumeration(type).classCount(); + String type = internalTypeEnumeration.nextType(); + int count = new DescriptorClassEnumeration(type).classCount(); if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) { @@ -296,19 +318,30 @@ implements MemberVisitor, parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1; } - // Also look at the return value. - type = internalTypeEnumeration.returnType(); - count = new DescriptorClassEnumeration(type).classCount(); - for (int counter = 0; counter < count; counter++) + // Copy the return type. { - referencedClasses[newReferencedClassIndex++] = - referencedClasses[referencedClassIndex++]; + String type = internalTypeEnumeration.returnType(); + int count = new DescriptorClassEnumeration(type).classCount(); + for (int counter = 0; counter < count; counter++) + { + referencedClasses[newReferencedClassIndex++] = + referencedClasses[referencedClassIndex++]; + } } - // Clear the unused entries. - while (newReferencedClassIndex < referencedClassIndex) + // Shrink the array to the proper size. + if (newReferencedClassIndex == 0) { - referencedClasses[newReferencedClassIndex++] = null; + referencedClasses = null; + } + else if (newReferencedClassIndex < referencedClassIndex) + { + Clazz[] newReferencedClasses = new Clazz[newReferencedClassIndex]; + System.arraycopy(referencedClasses, 0, + newReferencedClasses, 0, + newReferencedClassIndex); + + referencedClasses = newReferencedClasses; } } diff --git a/src/proguard/optimize/MethodStaticizer.java b/src/proguard/optimize/MethodStaticizer.java index c8bdd11..c672bfa 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 @@ implements MemberVisitor, { // Make the method static. programMethod.u2accessFlags = - (programMethod.getAccessFlags() & ~ClassConstants.INTERNAL_ACC_FINAL) | - ClassConstants.INTERNAL_ACC_STATIC; + (programMethod.getAccessFlags() & ~ClassConstants.ACC_FINAL) | + ClassConstants.ACC_STATIC; // Visit the method, if required. if (extraStaticMemberVisitor != null) diff --git a/src/proguard/optimize/OptimizationInfoMemberFilter.java b/src/proguard/optimize/OptimizationInfoMemberFilter.java index 2c5454c..bbfac20 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 8042825..20f4083 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,13 +23,12 @@ package proguard.optimize; import proguard.*; import proguard.classfile.*; import proguard.classfile.attribute.visitor.*; -import proguard.classfile.constant.Constant; import proguard.classfile.constant.visitor.*; import proguard.classfile.editor.*; import proguard.classfile.instruction.visitor.*; import proguard.classfile.util.MethodLinker; import proguard.classfile.visitor.*; -import proguard.evaluation.*; +import proguard.evaluation.InvocationUnit; import proguard.evaluation.value.*; import proguard.optimize.evaluation.*; import proguard.optimize.info.*; @@ -47,6 +46,7 @@ import java.util.*; public class Optimizer { private static final String CLASS_MARKING_FINAL = "class/marking/final"; + private static final String CLASS_UNBOXING_ENUM = "class/unboxing/enum"; private static final String CLASS_MERGING_VERTICAL = "class/merging/vertical"; private static final String CLASS_MERGING_HORIZONTAL = "class/merging/horizontal"; private static final String FIELD_REMOVAL_WRITEONLY = "field/removal/writeonly"; @@ -141,6 +141,7 @@ public class Optimizer new ConstantMatcher(true); boolean classMarkingFinal = filter.matches(CLASS_MARKING_FINAL); + boolean classUnboxingEnum = filter.matches(CLASS_UNBOXING_ENUM); boolean classMergingVertical = filter.matches(CLASS_MERGING_VERTICAL); boolean classMergingHorizontal = filter.matches(CLASS_MERGING_HORIZONTAL); boolean fieldRemovalWriteonly = filter.matches(FIELD_REMOVAL_WRITEONLY); @@ -171,6 +172,7 @@ public class Optimizer // Create counters to count the numbers of optimizations. ClassCounter classMarkingFinalCounter = new ClassCounter(); + ClassCounter classUnboxingEnumCounter = new ClassCounter(); ClassCounter classMergingVerticalCounter = new ClassCounter(); ClassCounter classMergingHorizontalCounter = new ClassCounter(); MemberCounter fieldRemovalWriteonlyCounter = new MemberCounter(); @@ -251,11 +253,13 @@ public class Optimizer libraryClassPool.classesAccept(new AllMemberVisitor(keepMarker)); // We also keep all classes that are involved in .class constructs. + // We're not looking at enum classes though, so they can be simplified. programClassPool.classesAccept( + new ClassAccessFilter(0, ClassConstants.ACC_ENUM, new AllMethodVisitor( new AllAttributeVisitor( new AllInstructionVisitor( - new DotClassClassVisitor(keepMarker))))); + new DotClassClassVisitor(keepMarker)))))); // We also keep all classes that are accessed dynamically. programClassPool.classesAccept( @@ -271,7 +275,7 @@ public class Optimizer // We also keep all bootstrap method signatures. programClassPool.classesAccept( - new ClassVersionFilter(ClassConstants.INTERNAL_CLASS_VERSION_1_7, + new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_7, new AllAttributeVisitor( new AttributeNameFilter(ClassConstants.ATTR_BootstrapMethods, new AllBootstrapMethodInfoVisitor( @@ -279,6 +283,32 @@ public class Optimizer new MethodrefTraveler( new ReferencedMemberVisitor(keepMarker)))))))); + // We also keep all bootstrap method arguments that point to methods. + // These arguments are typically the method handles for + // java.lang.invoke.LambdaMetafactory#metafactory, which provides the + // implementations for closures. + programClassPool.classesAccept( + new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_7, + new AllAttributeVisitor( + new AttributeNameFilter(ClassConstants.ATTR_BootstrapMethods, + new AllBootstrapMethodInfoVisitor( + new BootstrapMethodArgumentVisitor( + new MethodrefTraveler( + new ReferencedMemberVisitor(keepMarker)))))))); + + // We also keep all classes (and their methods) returned by dynamic + // method invocations. They may return dynamic implementations of + // interfaces that otherwise appear unused. + programClassPool.classesAccept( + new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_7, + new AllConstantVisitor( + new DynamicReturnedClassVisitor( + new MultiClassVisitor(new ClassVisitor[] + { + keepMarker, + new AllMemberVisitor(keepMarker) + }))))); + // Attach some optimization info to all classes and class members, so // it can be filled out later. programClassPool.classesAccept(new ClassOptimizationInfoSetter()); @@ -311,8 +341,9 @@ public class Optimizer { // Make methods final, whereever possible. programClassPool.classesAccept( + new ClassAccessFilter(0, ClassConstants.ACC_INTERFACE, new AllMethodVisitor( - new MethodFinalizer(methodMarkingFinalCounter))); + new MethodFinalizer(methodMarkingFinalCounter)))); } if (fieldRemovalWriteonly) @@ -337,6 +368,55 @@ public class Optimizer new ReadWriteFieldMarker())); } + if (classUnboxingEnum) + { + ClassCounter counter = new ClassCounter(); + + // Mark all final enums that qualify as simple enums. + programClassPool.classesAccept( + new ClassAccessFilter(ClassConstants.ACC_FINAL | + ClassConstants.ACC_ENUM, 0, + new SimpleEnumClassChecker())); + + // Count the preliminary number of simple enums. + programClassPool.classesAccept( + new SimpleEnumFilter(counter)); + + // Only continue checking simple enums if there are any candidates. + if (counter.getCount() > 0) + { + // Unmark all simple enums that are explicitly used as objects. + programClassPool.classesAccept( + new SimpleEnumUseChecker()); + + // Count the definitive number of simple enums. + programClassPool.classesAccept( + new SimpleEnumFilter(classUnboxingEnumCounter)); + + // Only start handling simple enums if there are any. + if (classUnboxingEnumCounter.getCount() > 0) + { + // Simplify the use of the enum classes in code. + programClassPool.classesAccept( + new AllMethodVisitor( + new AllAttributeVisitor( + new SimpleEnumUseSimplifier()))); + + // Simplify the static initializers of simple enum classes. + programClassPool.classesAccept( + new SimpleEnumFilter( + new SimpleEnumClassSimplifier())); + + // Simplify the use of the enum classes in descriptors. + programClassPool.classesAccept( + new SimpleEnumDescriptorSimplifier()); + + // Update references to class members with simple enum classes. + programClassPool.classesAccept(new MemberReferenceFixer()); + } + } + } + // Mark all used parameters, including the 'this' parameters. programClassPool.classesAccept( new AllMethodVisitor( @@ -354,25 +434,36 @@ public class Optimizer // programClassPool.classAccept("abc/Def", new NamedMethodVisitor("abc", null, new ClassPrinter())); // Perform partial evaluation for filling out fields, method parameters, - // and method return values. - ValueFactory valueFactory = new IdentifiedValueFactory(); - + // and method return values, so they can be propagated. if (fieldPropagationValue || methodPropagationParameter || methodPropagationReturnvalue) { - // Fill out fields, method parameters, and return values, so they - // can be propagated. + // We'll create values to be stored with fields, method parameters, + // and return values. + ValueFactory valueFactory = new ParticularValueFactory(); + ValueFactory detailedValueFactory = new DetailedValueFactory(); + InvocationUnit storingInvocationUnit = new StoringInvocationUnit(valueFactory, fieldPropagationValue, methodPropagationParameter, methodPropagationReturnvalue); + // Evaluate synthetic classes in more detail, notably to propagate + // the arrays of the classes generated for enum switch statements. + programClassPool.classesAccept( + new ClassAccessFilter(ClassConstants.ACC_SYNTHETIC, 0, + new AllMethodVisitor( + new AllAttributeVisitor( + new PartialEvaluator(detailedValueFactory, storingInvocationUnit, false))))); + + // Evaluate non-synthetic classes. programClassPool.classesAccept( + new ClassAccessFilter(0, ClassConstants.ACC_SYNTHETIC, new AllMethodVisitor( new AllAttributeVisitor( - new PartialEvaluator(valueFactory, storingInvocationUnit, false)))); + new PartialEvaluator(valueFactory, storingInvocationUnit, false))))); if (fieldPropagationValue) { @@ -397,8 +488,38 @@ public class Optimizer new AllMethodVisitor( new ConstantMemberFilter(methodPropagationReturnvalueCounter))); } + + if (classUnboxingEnumCounter.getCount() > 0) + { + // Propagate the simple enum constant counts. + programClassPool.classesAccept( + new SimpleEnumFilter( + new SimpleEnumArrayPropagator())); + } + + if (codeSimplificationAdvanced) + { + // Fill out constants into the arrays of synthetic classes, + // notably the arrays of the classes generated for enum switch + // statements. + InvocationUnit loadingInvocationUnit = + new LoadingInvocationUnit(valueFactory, + fieldPropagationValue, + methodPropagationParameter, + methodPropagationReturnvalue); + + programClassPool.classesAccept( + new ClassAccessFilter(ClassConstants.ACC_SYNTHETIC, 0, + new AllMethodVisitor( + new AllAttributeVisitor( + new PartialEvaluator(valueFactory, loadingInvocationUnit, false))))); + } } + // Perform partial evaluation again, now loading any previously stored + // values for fields, method parameters, and method return values. + ValueFactory valueFactory = new IdentifiedValueFactory(); + InvocationUnit loadingInvocationUnit = new LoadingInvocationUnit(valueFactory, fieldPropagationValue, @@ -446,7 +567,7 @@ public class Optimizer programClassPool.classesAccept( new AllMethodVisitor( new OptimizationInfoMemberFilter( - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_STATIC, + new MemberAccessFilter(0, ClassConstants.ACC_STATIC, new MethodStaticizer(methodMarkingStaticCounter))))); } @@ -548,6 +669,7 @@ public class Optimizer new DotClassMarker(), new MethodInvocationMarker(), new SuperInvocationMarker(), + new DynamicInvocationMarker(), new BackwardBranchMarker(), new AccessMethodMarker(), })), @@ -561,7 +683,8 @@ public class Optimizer if (classMergingVertical) { - // Merge classes into their superclasses or interfaces. + // Merge subclasses up into their superclasses or + // merge interfaces down into their implementing classes. programClassPool.classesAccept( new VerticalClassMerger(configuration.allowAccessModification, configuration.mergeInterfacesAggressively, @@ -593,8 +716,7 @@ public class Optimizer // Fix the access flags of referenced merged classes and their // class members. programClassPool.classesAccept( - new AllConstantVisitor( - new AccessFixer())); + new AccessFixer()); } // Fix the access flags of the inner classes information. @@ -667,9 +789,9 @@ public class Optimizer { // Make all non-private fields private, whereever possible. programClassPool.classesAccept( - new ClassAccessFilter(0, ClassConstants.INTERNAL_ACC_INTERFACE, + new ClassAccessFilter(0, ClassConstants.ACC_INTERFACE, new AllFieldVisitor( - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, new MemberPrivatizer(fieldMarkingPrivateCounter))))); } @@ -677,9 +799,9 @@ public class Optimizer { // Make all non-private methods private, whereever possible. programClassPool.classesAccept( - new ClassAccessFilter(0, ClassConstants.INTERNAL_ACC_INTERFACE, + new ClassAccessFilter(0, ClassConstants.ACC_INTERFACE, new AllMethodVisitor( - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, new MemberPrivatizer(methodMarkingPrivateCounter))))); } @@ -691,8 +813,7 @@ public class Optimizer // Fix the access flags of referenced classes and class members, // for MethodInliner. programClassPool.classesAccept( - new AllConstantVisitor( - new AccessFixer())); + new AccessFixer()); } if (methodRemovalParameterCounter .getCount() > 0 || @@ -842,6 +963,7 @@ public class Optimizer new ConstantPoolShrinker()); int classMarkingFinalCount = classMarkingFinalCounter .getCount(); + int classUnboxingEnumCount = classUnboxingEnumCounter .getCount(); int classMergingVerticalCount = classMergingVerticalCounter .getCount(); int classMergingHorizontalCount = classMergingHorizontalCounter .getCount(); int fieldRemovalWriteonlyCount = fieldRemovalWriteonlyCounter .getCount(); @@ -882,6 +1004,7 @@ public class Optimizer if (configuration.verbose) { System.out.println(" Number of finalized classes: " + classMarkingFinalCount + disabled(classMarkingFinal)); + System.out.println(" Number of unboxed enum classes: " + classUnboxingEnumCount + disabled(classUnboxingEnum)); System.out.println(" Number of vertically merged classes: " + classMergingVerticalCount + disabled(classMergingVertical)); System.out.println(" Number of horizontally merged classes: " + classMergingHorizontalCount + disabled(classMergingHorizontal)); System.out.println(" Number of removed write-only fields: " + fieldRemovalWriteonlyCount + disabled(fieldRemovalWriteonly)); @@ -911,6 +1034,7 @@ public class Optimizer } return classMarkingFinalCount > 0 || + classUnboxingEnumCount > 0 || classMergingVerticalCount > 0 || classMergingHorizontalCount > 0 || fieldRemovalWriteonlyCount > 0 || diff --git a/src/proguard/optimize/ParameterShrinker.java b/src/proguard/optimize/ParameterShrinker.java index 33d37d1..eb2592e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -29,7 +29,7 @@ import proguard.classfile.visitor.MemberVisitor; import proguard.optimize.info.ParameterUsageMarker; /** - * This MemberVisitor removes unused parameters from the code of the methods + * This AttributeVisitor removes unused parameters from the code of the methods * that it visits. * * @see ParameterUsageMarker @@ -41,7 +41,11 @@ public class ParameterShrinker extends SimplifiedVisitor implements AttributeVisitor { + //* private static final boolean DEBUG = false; + /*/ + private static boolean DEBUG = System.getProperty("ps") != null; + //*/ private final MemberVisitor extraVariableMemberVisitor; diff --git a/src/proguard/optimize/TailRecursionSimplifier.java b/src/proguard/optimize/TailRecursionSimplifier.java index f820566..dd38d6b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.*; -import proguard.classfile.constant.MethodrefConstant; +import proguard.classfile.constant.*; import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.editor.CodeAttributeComposer; import proguard.classfile.instruction.*; @@ -91,15 +91,14 @@ implements AttributeVisitor, int accessFlags = method.getAccessFlags(); if (// Only check the method if it is private, static, or final. - (accessFlags & (ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_STATIC | - ClassConstants.INTERNAL_ACC_FINAL)) != 0 && + (accessFlags & (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC | + ClassConstants.ACC_FINAL)) != 0 && // Only check 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) + (accessFlags & (ClassConstants.ACC_SYNCHRONIZED | + ClassConstants.ACC_NATIVE | + ClassConstants.ACC_ABSTRACT)) == 0) { // codeAttributeComposer.DEBUG = DEBUG = // clazz.getName().equals("abc/Def") && @@ -254,7 +253,7 @@ implements AttributeVisitor, // Implementations for ConstantVisitor. - public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) + public void visitAnyMethodrefConstant(Clazz clazz, RefConstant methodrefConstant) { recursive = targetMethod.equals(methodrefConstant.referencedMember); } @@ -280,7 +279,7 @@ implements AttributeVisitor, String descriptor = method.getDescriptor(clazz); boolean isStatic = - (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0; + (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0; // Count the number of parameters, taking into account their categories. int parameterSize = ClassUtil.internalMethodParameterSize(descriptor); @@ -314,23 +313,23 @@ implements AttributeVisitor, byte opcode; switch (parameterType.charAt(0)) { - case ClassConstants.INTERNAL_TYPE_BOOLEAN: - case ClassConstants.INTERNAL_TYPE_BYTE: - case ClassConstants.INTERNAL_TYPE_CHAR: - case ClassConstants.INTERNAL_TYPE_SHORT: - case ClassConstants.INTERNAL_TYPE_INT: + case ClassConstants.TYPE_BOOLEAN: + case ClassConstants.TYPE_BYTE: + case ClassConstants.TYPE_CHAR: + case ClassConstants.TYPE_SHORT: + case ClassConstants.TYPE_INT: opcode = InstructionConstants.OP_ISTORE; break; - case ClassConstants.INTERNAL_TYPE_LONG: + case ClassConstants.TYPE_LONG: opcode = InstructionConstants.OP_LSTORE; break; - case ClassConstants.INTERNAL_TYPE_FLOAT: + case ClassConstants.TYPE_FLOAT: opcode = InstructionConstants.OP_FSTORE; break; - case ClassConstants.INTERNAL_TYPE_DOUBLE: + case ClassConstants.TYPE_DOUBLE: opcode = InstructionConstants.OP_DSTORE; break; diff --git a/src/proguard/optimize/WriteOnlyFieldFilter.java b/src/proguard/optimize/WriteOnlyFieldFilter.java index 762bd91..7aad651 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 2e86532..daccec1 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +30,7 @@ import proguard.classfile.instruction.*; import proguard.classfile.instruction.visitor.InstructionVisitor; import proguard.classfile.util.*; import proguard.classfile.visitor.*; -import proguard.evaluation.*; +import proguard.evaluation.TracedStack; import proguard.evaluation.value.*; import proguard.optimize.info.*; @@ -50,8 +50,8 @@ implements AttributeVisitor private static final boolean DEBUG_RESULTS = false; private static final boolean DEBUG = false; /*/ - private static boolean DEBUG_RESULTS = true; - private static boolean DEBUG = true; + private static boolean DEBUG = System.getProperty("es") != null; + private static boolean DEBUG_RESULTS = DEBUG; //*/ private static final int UNSUPPORTED = -1; @@ -177,11 +177,7 @@ implements AttributeVisitor if (DEBUG_RESULTS) { System.out.println(); - System.out.println("Class "+ClassUtil.externalClassName(clazz.getName())); - System.out.println("Method "+ClassUtil.externalFullMethodDescription(clazz.getName(), - 0, - method.getName(clazz), - method.getDescriptor(clazz))); + System.out.println("EvaluationShrinker ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]"); } // Initialize the necessary array. @@ -542,7 +538,7 @@ implements AttributeVisitor int parameterSize = ParameterUsageMarker.getParameterSize(programMethod); // Make the method invocation static, if possible. - if ((programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) == 0 && + if ((programMethod.getAccessFlags() & ClassConstants.ACC_STATIC) == 0 && !ParameterUsageMarker.isParameterUsed(programMethod, 0)) { replaceByStaticInvocation(programClass, @@ -705,7 +701,7 @@ implements AttributeVisitor { // Mark any variable initializations for this variable load that // are required according to the JVM. - markVariableInitializers(offset, variableInstruction.variableIndex); + markVariableInitializersBefore(offset, variableInstruction.variableIndex); } } } @@ -729,6 +725,8 @@ implements AttributeVisitor if (isInstructionNecessary(offset)) { // Check all stack entries that are popped. + // Unusual case: an exception handler with an exception that is + // no longer consumed directly by a method. // Typical case: a freshly marked variable initialization that // requires some value on the stack. int popCount = instruction.stackPopCount(clazz); @@ -739,17 +737,36 @@ implements AttributeVisitor int stackSize = tracedStack.size(); + int requiredPopCount = 0; int requiredPushCount = 0; for (int stackIndex = stackSize - popCount; stackIndex < stackSize; stackIndex++) { - if (!isStackSimplifiedBefore(offset, stackIndex)) + boolean stackSimplifiedBefore = + isStackSimplifiedBefore(offset, stackIndex); + boolean stackEntryPresentBefore = + isStackEntryPresentBefore(offset, stackIndex); + + if (stackSimplifiedBefore) { // Is this stack entry pushed by any producer - // (because it is required by other consumers)? + // (maybe an exception in an exception handler)? if (isStackEntryPresentBefore(offset, stackIndex)) { // Mark all produced stack entries. markStackEntryProducers(offset, stackIndex); + + // Remember to pop it. + requiredPopCount++; + } + } + else + { + // Is this stack entry pushed by any producer + // (because it is required by other consumers)? + if (stackEntryPresentBefore) + { + // Mark all produced stack entries. + markStackEntryProducers(offset, stackIndex); } else { @@ -759,6 +776,14 @@ implements AttributeVisitor } } + // Pop some unnecessary stack entries. + if (requiredPopCount > 0) + { + if (DEBUG) System.out.println(" Inserting before marked consumer "+instruction.toString(offset)); + + insertPopInstructions(offset, false, true, popCount); + } + // Push some necessary stack entries. if (requiredPushCount > 0) { @@ -769,7 +794,7 @@ implements AttributeVisitor throw new IllegalArgumentException("Unsupported stack size increment ["+requiredPushCount+"] at ["+offset+"]"); } - insertPushInstructions(offset, false, tracedStack.getTop(0).computationalType()); + insertPushInstructions(offset, false, true, tracedStack.getTop(0).computationalType()); } } @@ -826,7 +851,7 @@ implements AttributeVisitor { if (DEBUG) System.out.println(" Inserting after marked producer "+instruction.toString(offset)); - insertPopInstructions(offset, false, requiredPopCount); + insertPopInstructions(offset, false, false, requiredPopCount); } } } @@ -863,7 +888,7 @@ implements AttributeVisitor { if (DEBUG) System.out.println(" Replacing unmarked consumer "+instruction.toString(offset)); - insertPopInstructions(offset, true, expectedPopCount); + insertPopInstructions(offset, true, false, expectedPopCount); } } @@ -893,7 +918,7 @@ implements AttributeVisitor { if (DEBUG) System.out.println(" Replacing unmarked producer "+instruction.toString(offset)); - insertPushInstructions(offset, true, tracedStack.getTop(0).computationalType()); + insertPushInstructions(offset, true, false, tracedStack.getTop(0).computationalType()); } } } @@ -1434,35 +1459,65 @@ implements AttributeVisitor /** - * 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. + * Ensures that the given variable is initialized before the specified + * consumer of that variable, in the JVM's view. + * @param consumerOffset the instruction offset before which the variable + * needs to be initialized. + * @param variableIndex the index of the variable. */ - private void markVariableInitializers(int consumerOffset, - int variableIndex) + private void markVariableInitializersBefore(int consumerOffset, + int variableIndex) { + // Make sure the variable is initialized after all producers. + // Use the simple evaluator, to get the JVM's view of what is + // initialized. InstructionOffsetValue producerOffsets = simplePartialEvaluator.getVariablesBefore(consumerOffset).getProducerValue(variableIndex).instructionOffsetValue(); - if (producerOffsets != null) + int offsetCount = producerOffsets.instructionOffsetCount(); + for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++) { - int offsetCount = producerOffsets.instructionOffsetCount(); - for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++) + // Avoid infinite loops by only looking at producers before + // the consumer. + int producerOffset = + producerOffsets.instructionOffset(offsetIndex); + if (producerOffset < consumerOffset) { - // Make sure the variable and the instruction are marked - // at the producing offset. - int offset = producerOffsets.instructionOffset(offsetIndex); + markVariableInitializersAfter(producerOffset, variableIndex); + } + } + } - if (!isInstructionNecessary(offset) && - isVariableInitialization(offset, variableIndex)) - { - if (DEBUG) System.out.print(" Marking initialization of v"+variableIndex+" at "); - markInstruction(offset); + /** + * Ensures that the given variable is initialized after the specified + * producer of that variable, in the JVM's view. + * @param producerOffset the instruction offset after which the variable + * needs to be initialized. + * @param variableIndex the index of the variable. + */ + private void markVariableInitializersAfter(int producerOffset, + int variableIndex) + { + // No problem if the producer has already been marked. + if (!isInstructionNecessary(producerOffset)) + { + // Is the unmarked producer a variable initialization? + if (isVariableInitialization(producerOffset, variableIndex)) + { + // Mark the producer. + if (DEBUG) System.out.print(" Marking initialization of v"+variableIndex+" at "); - if (DEBUG) System.out.println(); - } + markInstruction(producerOffset); + + if (DEBUG) System.out.println(); + } + else + { + // Don't mark the producer, but recursively look at the + // preceding producers of the same variable. Their values + // will fall through, replacing this producer. + markVariableInitializersBefore(producerOffset, variableIndex); } } } @@ -1645,6 +1700,7 @@ implements AttributeVisitor */ private void insertPushInstructions(int offset, boolean replace, + boolean before, int computationalType) { // Mark this instruction. @@ -1657,21 +1713,7 @@ implements AttributeVisitor if (DEBUG) System.out.println(": "+replacementInstruction.toString(offset)); // Replace or insert the push instruction. - if (replace) - { - // Replace the push instruction. - codeAttributeEditor.replaceInstruction(offset, replacementInstruction); - } - else - { - // Insert the push instruction. - codeAttributeEditor.insertBeforeInstruction(offset, replacementInstruction); - - if (extraAddedInstructionVisitor != null) - { - replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor); - } - } + insertInstruction(offset, replace, before, replacementInstruction); } @@ -1700,7 +1742,10 @@ implements AttributeVisitor * Pops the given number of stack entries at or after the given offset. * The instructions are marked as necessary. */ - private void insertPopInstructions(int offset, boolean replace, int popCount) + private void insertPopInstructions(int offset, + boolean replace, + boolean before, + int popCount) { // Mark this instruction. markInstruction(offset); @@ -1713,19 +1758,7 @@ implements AttributeVisitor Instruction popInstruction = new SimpleInstruction(InstructionConstants.OP_POP); - if (replace) - { - codeAttributeEditor.replaceInstruction(offset, popInstruction); - } - else - { - codeAttributeEditor.insertAfterInstruction(offset, popInstruction); - - if (extraAddedInstructionVisitor != null) - { - popInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor); - } - } + insertInstruction(offset, replace, before, popInstruction); break; } case 2: @@ -1734,19 +1767,7 @@ implements AttributeVisitor Instruction popInstruction = new SimpleInstruction(InstructionConstants.OP_POP2); - if (replace) - { - codeAttributeEditor.replaceInstruction(offset, popInstruction); - } - else - { - codeAttributeEditor.insertAfterInstruction(offset, popInstruction); - - if (extraAddedInstructionVisitor != null) - { - popInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor); - } - } + insertInstruction(offset, replace, before, popInstruction); break; } default: @@ -1771,31 +1792,86 @@ implements AttributeVisitor popInstructions[popCount / 2] = popInstruction; } - if (replace) - { - codeAttributeEditor.replaceInstruction(offset, popInstructions); + insertInstructions(offset, + replace, + before, + popInstruction, + popInstructions); + break; + } + } + } - for (int index = 1; index < popInstructions.length; index++) - { - if (extraAddedInstructionVisitor != null) - { - popInstructions[index].accept(null, null, null, offset, extraAddedInstructionVisitor); - } - } - } - else + + /** + * Inserts or replaces the given instruction at the given offset. + */ + private void insertInstruction(int offset, + boolean replace, + boolean before, + Instruction instruction) + { + if (replace) + { + codeAttributeEditor.replaceInstruction(offset, instruction); + } + else + { + if (before) + { + codeAttributeEditor.insertBeforeInstruction(offset, instruction); + } + else + { + codeAttributeEditor.insertAfterInstruction(offset, instruction); + } + + if (extraAddedInstructionVisitor != null) + { + instruction.accept(null, null, null, offset, extraAddedInstructionVisitor); + } + } + } + + + /** + * Inserts or replaces the given instruction at the given offset. + */ + private void insertInstructions(int offset, + boolean replace, + boolean before, + Instruction instruction, + Instruction[] instructions) + { + if (replace) + { + codeAttributeEditor.replaceInstruction(offset, instructions); + + if (extraAddedInstructionVisitor != null) + { + for (int index = 1; index < instructions.length; index++) { - codeAttributeEditor.insertAfterInstruction(offset, popInstructions); + instructions[index].accept(null, null, null, offset, extraAddedInstructionVisitor); + } + } + } + else + { + if (before) + { + codeAttributeEditor.insertBeforeInstruction(offset, instructions); + } + else + { + codeAttributeEditor.insertAfterInstruction(offset, instructions); + } - for (int index = 0; index < popInstructions.length; index++) - { - if (extraAddedInstructionVisitor != null) - { - popInstructions[index].accept(null, null, null, offset, extraAddedInstructionVisitor); - } - } + for (int index = 0; index < instructions.length; index++) + { + if (extraAddedInstructionVisitor != null) + { + instructions[index].accept(null, null, null, offset, extraAddedInstructionVisitor); } - break; } } } @@ -1998,14 +2074,14 @@ implements AttributeVisitor int variableIndex) { // Wasn't the variable set yet? - Value valueBefore = partialEvaluator.getVariablesBefore(instructionOffset).getValue(variableIndex); + Value valueBefore = simplePartialEvaluator.getVariablesBefore(instructionOffset).getValue(variableIndex); if (valueBefore == null) { return true; } // Is the computational type different now? - Value valueAfter = partialEvaluator.getVariablesAfter(instructionOffset).getValue(variableIndex); + Value valueAfter = simplePartialEvaluator.getVariablesAfter(instructionOffset).getValue(variableIndex); if (valueAfter.computationalType() != valueBefore.computationalType()) { return true; @@ -2020,7 +2096,7 @@ implements AttributeVisitor } // Was the producer an argument (which may be removed)? - Value producersBefore = partialEvaluator.getVariablesBefore(instructionOffset).getProducerValue(variableIndex); + Value producersBefore = simplePartialEvaluator.getVariablesBefore(instructionOffset).getProducerValue(variableIndex); return producersBefore.instructionOffsetValue().instructionOffsetCount() == 1 && producersBefore.instructionOffsetValue().instructionOffset(0) == PartialEvaluator.AT_METHOD_ENTRY; } diff --git a/src/proguard/optimize/evaluation/EvaluationSimplifier.java b/src/proguard/optimize/evaluation/EvaluationSimplifier.java index e6e73d9..8187342 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,12 @@ import proguard.classfile.editor.*; import proguard.classfile.instruction.*; import proguard.classfile.instruction.visitor.InstructionVisitor; import proguard.classfile.util.*; -import proguard.classfile.visitor.*; -import proguard.evaluation.*; +import proguard.classfile.visitor.ClassPrinter; +import proguard.evaluation.TracedVariables; import proguard.evaluation.value.*; -import proguard.optimize.info.*; +import proguard.optimize.info.SideEffectInstructionChecker; + +import java.util.Arrays; /** * This AttributeVisitor simplifies the code attributes that it visits, based @@ -49,7 +51,7 @@ implements AttributeVisitor, //* private static final boolean DEBUG = false; /*/ - private static boolean DEBUG = true; + private static boolean DEBUG = System.getProperty("es") != null; //*/ private final InstructionVisitor extraInstructionVisitor; @@ -125,11 +127,7 @@ implements AttributeVisitor, if (DEBUG) { System.out.println(); - System.out.println("Class "+ClassUtil.externalClassName(clazz.getName())); - System.out.println("Method "+ClassUtil.externalFullMethodDescription(clazz.getName(), - 0, - method.getName(clazz), - method.getDescriptor(clazz))); + System.out.println("EvaluationSimplifier ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]"); } // Evaluate the method. @@ -185,6 +183,7 @@ implements AttributeVisitor, case InstructionConstants.OP_I2B: case InstructionConstants.OP_I2C: case InstructionConstants.OP_I2S: + case InstructionConstants.OP_ARRAYLENGTH: replaceIntegerPushInstruction(clazz, offset, simpleInstruction); break; @@ -354,15 +353,50 @@ implements AttributeVisitor, } - public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction) + public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction) { // First try to simplify it to a simple branch. - replaceBranchInstruction(clazz, offset, switchInstruction); + replaceBranchInstruction(clazz, offset, tableSwitchInstruction); - // Otherwise make sure all branch targets are valid. + // Otherwise try to simplify simple enum switches. if (!codeAttributeEditor.isModified(offset)) { - replaceSwitchInstruction(clazz, offset, switchInstruction); + replaceSimpleEnumSwitchInstruction(clazz, + codeAttribute, + offset, + tableSwitchInstruction); + + // Otherwise make sure all branch targets are valid. + if (!codeAttributeEditor.isModified(offset)) + { + cleanUpSwitchInstruction(clazz, offset, tableSwitchInstruction); + + trimSwitchInstruction(clazz, offset, tableSwitchInstruction); + } + } + } + + + public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) + { + // First try to simplify it to a simple branch. + replaceBranchInstruction(clazz, offset, lookUpSwitchInstruction); + + // Otherwise try to simplify simple enum switches. + if (!codeAttributeEditor.isModified(offset)) + { + replaceSimpleEnumSwitchInstruction(clazz, + codeAttribute, + offset, + lookUpSwitchInstruction); + + // Otherwise make sure all branch targets are valid. + if (!codeAttributeEditor.isModified(offset)) + { + cleanUpSwitchInstruction(clazz, offset, lookUpSwitchInstruction); + + trimSwitchInstruction(clazz, offset, lookUpSwitchInstruction); + } } } @@ -824,9 +858,185 @@ implements AttributeVisitor, /** + * Replaces the given table switch instruction, if it is based on the value + * of a fixed array. This is typical for switches on simple enums. + */ + private void replaceSimpleEnumSwitchInstruction(Clazz clazz, + CodeAttribute codeAttribute, + int offset, + TableSwitchInstruction tableSwitchInstruction) + { + // Check if the switch instruction is consuming a single value loaded + // from a fully specified array. + InstructionOffsetValue producerOffsets = + partialEvaluator.getStackBefore(offset).getTopProducerValue(0).instructionOffsetValue(); + + if (producerOffsets.instructionOffsetCount() == 1) + { + int producerOffset = producerOffsets.instructionOffset(0); + + if (codeAttribute.code[producerOffset] == InstructionConstants.OP_IALOAD && + !codeAttributeEditor.isModified(producerOffset)) + { + ReferenceValue referenceValue = + partialEvaluator.getStackBefore(producerOffset).getTop(1).referenceValue(); + + if (referenceValue.isParticular()) + { + // Simplify the entire construct. + replaceSimpleEnumSwitchInstruction(clazz, + codeAttribute, + producerOffset, + offset, + tableSwitchInstruction, + referenceValue); + } + } + } + } + + + /** + * Replaces the given table switch instruction that is based on a value of + * the given fixed array. + */ + private void replaceSimpleEnumSwitchInstruction(Clazz clazz, + CodeAttribute codeAttribute, + int loadOffset, + int switchOffset, + TableSwitchInstruction tableSwitchInstruction, + ReferenceValue mappingValue) + { + ValueFactory valueFactory = new ParticularValueFactory(); + + // Transform the jump offsets. + int[] jumpOffsets = tableSwitchInstruction.jumpOffsets; + int[] newJumpOffsets = new int[mappingValue.arrayLength(valueFactory).value()]; + + for (int index = 0; index < newJumpOffsets.length; index++) + { + int switchCase = + mappingValue.integerArrayLoad(valueFactory.createIntegerValue( + index), + valueFactory).value(); + + newJumpOffsets[index] = + switchCase >= tableSwitchInstruction.lowCase && + switchCase <= tableSwitchInstruction.highCase ? + jumpOffsets[switchCase - tableSwitchInstruction.lowCase] : + tableSwitchInstruction.defaultOffset; + } + + // Update the instruction. + tableSwitchInstruction.lowCase = 0; + tableSwitchInstruction.highCase = newJumpOffsets.length - 1; + tableSwitchInstruction.jumpOffsets = newJumpOffsets; + + // Replace the original one with the new version. + replaceSimpleEnumSwitchInstruction(clazz, + loadOffset, + switchOffset, + tableSwitchInstruction); + + cleanUpSwitchInstruction(clazz, switchOffset, tableSwitchInstruction); + + trimSwitchInstruction(clazz, switchOffset, tableSwitchInstruction); + } + + + /** + * Replaces the given look up switch instruction, if it is based on the + * value of a fixed array. This is typical for switches on simple enums. + */ + private void replaceSimpleEnumSwitchInstruction(Clazz clazz, + CodeAttribute codeAttribute, + int offset, + LookUpSwitchInstruction lookupSwitchInstruction) + { + // Check if the switch instruction is consuming a single value loaded + // from a fully specified array. + InstructionOffsetValue producerOffsets = + partialEvaluator.getStackBefore(offset).getTopProducerValue(0).instructionOffsetValue(); + + if (producerOffsets.instructionOffsetCount() == 1) + { + int producerOffset = producerOffsets.instructionOffset(0); + + if (codeAttribute.code[producerOffset] == InstructionConstants.OP_IALOAD && + !codeAttributeEditor.isModified(producerOffset)) + { + ReferenceValue referenceValue = + partialEvaluator.getStackBefore(producerOffset).getTop(1).referenceValue(); + + if (referenceValue.isParticular()) + { + // Simplify the entire construct. + replaceSimpleEnumSwitchInstruction(clazz, + codeAttribute, + producerOffset, + offset, + lookupSwitchInstruction, + referenceValue); + } + } + } + } + + + /** + * Replaces the given look up switch instruction that is based on a value of + * the given fixed array. This is typical for switches on simple enums. + */ + private void replaceSimpleEnumSwitchInstruction(Clazz clazz, + CodeAttribute codeAttribute, + int loadOffset, + int switchOffset, + LookUpSwitchInstruction lookupSwitchInstruction, + ReferenceValue mappingValue) + { + ValueFactory valueFactory = new ParticularValueFactory(); + + // Transform the jump offsets. + int[] cases = lookupSwitchInstruction.cases; + int[] jumpOffsets = lookupSwitchInstruction.jumpOffsets; + int[] newJumpOffsets = new int[mappingValue.arrayLength(valueFactory).value()]; + + for (int index = 0; index < newJumpOffsets.length; index++) + { + int switchCase = + mappingValue.integerArrayLoad(valueFactory.createIntegerValue(index), + valueFactory).value(); + + int caseIndex = Arrays.binarySearch(cases, switchCase); + + newJumpOffsets[index] = caseIndex >= 0 ? + jumpOffsets[caseIndex] : + lookupSwitchInstruction.defaultOffset; + } + + // Replace the original lookup switch with a table switch. + TableSwitchInstruction replacementSwitchInstruction = + new TableSwitchInstruction(InstructionConstants.OP_TABLESWITCH, + lookupSwitchInstruction.defaultOffset, + 0, + newJumpOffsets.length - 1, + newJumpOffsets); + + replaceSimpleEnumSwitchInstruction(clazz, + loadOffset, + switchOffset, + replacementSwitchInstruction); + + cleanUpSwitchInstruction(clazz, switchOffset, replacementSwitchInstruction); + + trimSwitchInstruction(clazz, switchOffset, replacementSwitchInstruction); + } + + + /** * Makes sure all branch targets of the given switch instruction are valid. */ - private void replaceSwitchInstruction(Clazz clazz, + private void cleanUpSwitchInstruction(Clazz clazz, int offset, SwitchInstruction switchInstruction) { @@ -872,6 +1082,129 @@ implements AttributeVisitor, /** + * Trims redundant offsets from the given switch instruction. + */ + private void trimSwitchInstruction(Clazz clazz, + int offset, + TableSwitchInstruction tableSwitchInstruction) + { + // Get an offset that can serve as a valid default offset. + int defaultOffset = tableSwitchInstruction.defaultOffset; + int[] jumpOffsets = tableSwitchInstruction.jumpOffsets; + int length = jumpOffsets.length; + + // Find the lowest index with a non-default jump offset. + int lowIndex = 0; + while (lowIndex < length && + jumpOffsets[lowIndex] == defaultOffset) + { + lowIndex++; + } + + // Find the highest index with a non-default jump offset. + int highIndex = length - 1; + while (highIndex >= 0 && + jumpOffsets[highIndex] == defaultOffset) + { + highIndex--; + } + + // Can we use a shorter array? + int newLength = highIndex - lowIndex + 1; + if (newLength < length) + { + if (newLength <= 0) + { + // Replace the switch instruction by a simple branch instruction. + Instruction replacementInstruction = + new BranchInstruction(InstructionConstants.OP_GOTO, + defaultOffset); + + replaceInstruction(clazz, offset, tableSwitchInstruction, + replacementInstruction); + } + else + { + // Trim the array. + int[] newJumpOffsets = new int[newLength]; + + System.arraycopy(jumpOffsets, lowIndex, newJumpOffsets, 0, newLength); + + tableSwitchInstruction.jumpOffsets = newJumpOffsets; + tableSwitchInstruction.lowCase += lowIndex; + tableSwitchInstruction.highCase -= length - newLength - lowIndex; + + replaceInstruction(clazz, offset, tableSwitchInstruction, + tableSwitchInstruction); + } + } + } + + + /** + * Trims redundant offsets from the given switch instruction. + */ + private void trimSwitchInstruction(Clazz clazz, + int offset, + LookUpSwitchInstruction lookUpSwitchInstruction) + { + // Get an offset that can serve as a valid default offset. + int defaultOffset = lookUpSwitchInstruction.defaultOffset; + int[] jumpOffsets = lookUpSwitchInstruction.jumpOffsets; + int length = jumpOffsets.length; + int newLength = length; + + // Count the default jump offsets. + for (int index = 0; index < length; index++) + { + if (jumpOffsets[index] == defaultOffset) + { + newLength--; + } + } + + // Can we use shorter arrays? + if (newLength < length) + { + if (newLength <= 0) + { + // Replace the switch instruction by a simple branch instruction. + Instruction replacementInstruction = + new BranchInstruction(InstructionConstants.OP_GOTO, + defaultOffset); + + replaceInstruction(clazz, offset, lookUpSwitchInstruction, + replacementInstruction); + } + else + { + // Remove redundant entries from the arrays. + int[] cases = lookUpSwitchInstruction.cases; + int[] newJumpOffsets = new int[newLength]; + int[] newCases = new int[newLength]; + + int newIndex = 0; + + for (int index = 0; index < length; index++) + { + if (jumpOffsets[index] != defaultOffset) + { + newJumpOffsets[newIndex] = jumpOffsets[index]; + newCases[newIndex++] = cases[index]; + } + } + + lookUpSwitchInstruction.jumpOffsets = newJumpOffsets; + lookUpSwitchInstruction.cases = newCases; + + replaceInstruction(clazz, offset, lookUpSwitchInstruction, + lookUpSwitchInstruction); + } + } + } + + + /** * Replaces the given instruction by an infinite loop. */ private void replaceByInfiniteLoop(Clazz clazz, @@ -891,7 +1224,11 @@ implements AttributeVisitor, { // Note: we're not passing the right arguments for now, knowing that // they aren't used anyway. - instruction.accept(clazz, null, null, offset, extraInstructionVisitor); + instruction.accept(clazz, + null, + null, + offset, + extraInstructionVisitor); } } @@ -985,4 +1322,39 @@ implements AttributeVisitor, } } } + + + /** + * Replaces the simple enum switch instructions at a given offsets by a + * given replacement instruction. + */ + private void replaceSimpleEnumSwitchInstruction(Clazz clazz, + int loadOffset, + int switchOffset, + SwitchInstruction replacementSwitchInstruction) + { + if (DEBUG) System.out.println(" Replacing switch instruction at ["+switchOffset+"] -> ["+loadOffset+"] swap + pop, "+replacementSwitchInstruction.toString(switchOffset)+")"); + + // Remove the array load instruction. + codeAttributeEditor.replaceInstruction(loadOffset, new Instruction[] + { + new SimpleInstruction(InstructionConstants.OP_SWAP), + new SimpleInstruction(InstructionConstants.OP_POP), + }); + + // Replace the switch instruction. + codeAttributeEditor.replaceInstruction(switchOffset, replacementSwitchInstruction); + + // Visit the instruction, if required. + if (extraInstructionVisitor != null) + { + // Note: we're not passing the right arguments for now, knowing that + // they aren't used anyway. + replacementSwitchInstruction.accept(clazz, + null, + null, + switchOffset, + extraInstructionVisitor); + } + } } diff --git a/src/proguard/optimize/evaluation/LivenessAnalyzer.java b/src/proguard/optimize/evaluation/LivenessAnalyzer.java index 5ce8ccb..87bd4e5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/LoadingInvocationUnit.java b/src/proguard/optimize/evaluation/LoadingInvocationUnit.java index d6baa67..80b4b84 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.evaluation.BasicInvocationUnit; import proguard.evaluation.value.*; /** - * This InvocationUbit loads parameter values and return values that were + * This InvocationUnit loads parameter values and return values that were * previously stored with the methods that are invoked. * * @see StoringInvocationUnit @@ -45,7 +45,7 @@ extends BasicInvocationUnit */ public LoadingInvocationUnit(ValueFactory valueFactory) { - this(valueFactory, false, false, false); + this(valueFactory, true, true, true); } @@ -80,8 +80,7 @@ extends BasicInvocationUnit { // Retrieve the stored field class value. ReferenceValue value = StoringInvocationUnit.getFieldClassValue((Field)referencedMember); - if (value != null && - value.isParticular()) + if (value != null) { return value; } @@ -104,8 +103,7 @@ extends BasicInvocationUnit { // Retrieve the stored field value. Value value = StoringInvocationUnit.getFieldValue((Field)referencedMember); - if (value != null && - value.isParticular()) + if (value != null) { return value; } @@ -126,8 +124,7 @@ extends BasicInvocationUnit { // Retrieve the stored method parameter value. Value value = StoringInvocationUnit.getMethodParameterValue(method, parameterIndex); - if (value != null && - value.isParticular()) + if (value != null) { return value; } @@ -153,8 +150,7 @@ extends BasicInvocationUnit { // Retrieve the stored method return value. Value value = StoringInvocationUnit.getMethodReturnValue((Method)referencedMember); - if (value != null && - value.isParticular()) + if (value != null) { return value; } @@ -165,31 +161,4 @@ extends BasicInvocationUnit refConstant, type); } - - -// // Small utility methods. -// -// private Value refresh(Value value) -// { -// if (value.isParticular()) -// { -// return value; -// } -// -// switch (value.computationalType()) -// { -// case Value.TYPE_INTEGER: return valueFactory.createIntegerValue(); -// case Value.TYPE_LONG: return valueFactory.createLongValue(); -// case Value.TYPE_FLOAT: return valueFactory.createFloatValue(); -// case Value.TYPE_DOUBLE: return valueFactory.createDoubleValue(); -// default: -// { -// ReferenceValue referenceValue = value.referenceValue(); -// -// return valueFactory.createReferenceValue(referenceValue.getType(), -// referenceValue.getReferencedClass(), -// referenceValue.isNull() != Value.NEVER); -// } -// } -// } } diff --git a/src/proguard/optimize/evaluation/PartialEvaluator.java b/src/proguard/optimize/evaluation/PartialEvaluator.java index 6a5bedf..0301f12 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -96,9 +96,10 @@ implements AttributeVisitor, * during evaluation. * @param invocationUnit the invocation unit that will handle all * communication with other fields and methods. - * @param evaluateAllCode a flag that specifies whether all branch targets - * and exception handlers should be evaluated, - * even if they are unreachable. + * @param evaluateAllCode a flag that specifies whether all casts, branch + * targets, and exception handlers should be + * evaluated, even if they are unnecessary or + * unreachable. */ public PartialEvaluator(ValueFactory valueFactory, InvocationUnit invocationUnit, @@ -132,17 +133,22 @@ implements AttributeVisitor, /** * Creates a new PartialEvaluator. - * @param valueFactory the value factory that will create all - * values during evaluation. - * @param invocationUnit the invocation unit that will handle all - * communication with other fields and methods. - * @param evaluateAllCode a flag that specifies whether all branch - * targets and exception handlers should be - * evaluated, even if they are unreachable. - * @param branchUnit the branch unit that will handle all - * branches. - * @param branchTargetFinder the utility class that will find all - * branches. + * @param valueFactory the value factory that will create + * all values during evaluation. + * @param invocationUnit the invocation unit that will handle + * all communication with other fields + * and methods. + * @param evaluateAllCode a flag that specifies whether all + * casts, branch targets, and exception + * handlers should be evaluated, even + * if they are unnecessary or + * unreachable. + * @param branchUnit the branch unit that will handle all + * branches. + * @param branchTargetFinder the utility class that will find all + * branches. + * @param callingInstructionBlockStack the stack of instruction blocks to + * be evaluated */ private PartialEvaluator(ValueFactory valueFactory, InvocationUnit invocationUnit, @@ -293,7 +299,7 @@ implements AttributeVisitor, if (isTraced(offset)) { int initializationOffset = branchTargetFinder.initializationOffset(offset); - if (initializationOffset != NONE) + if (initializationOffset >= 0) { System.out.println(" is to be initialized at ["+initializationOffset+"]"); } @@ -639,7 +645,8 @@ implements AttributeVisitor, stack, valueFactory, branchUnit, - invocationUnit); + invocationUnit, + evaluateAllCode); int instructionOffset = startOffset; @@ -1055,7 +1062,7 @@ implements AttributeVisitor, //stack.push(valueFactory.createReference((ClassConstant)((ProgramClass)clazz).getConstant(exceptionInfo.u2catchType), false)); String catchClassName = catchType != 0 ? clazz.getClassName(catchType) : - ClassConstants.INTERNAL_NAME_JAVA_LANG_THROWABLE; + ClassConstants.NAME_JAVA_LANG_THROWABLE; Clazz catchClass = catchType != 0 ? ((ClassConstant)((ProgramClass)clazz).getConstant(catchType)).referencedClass : diff --git a/src/proguard/optimize/evaluation/SimpleEnumArrayPropagator.java b/src/proguard/optimize/evaluation/SimpleEnumArrayPropagator.java new file mode 100644 index 0000000..d6aaf7d --- /dev/null +++ b/src/proguard/optimize/evaluation/SimpleEnumArrayPropagator.java @@ -0,0 +1,94 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.evaluation; + +import proguard.classfile.*; +import proguard.classfile.util.SimplifiedVisitor; +import proguard.classfile.visitor.*; +import proguard.evaluation.value.*; +import proguard.optimize.info.*; + +/** + * This ClassVisitor propagates the value of the $VALUES field to the values() + * method in the simple enum classes that it visits. + * + * @see SimpleEnumMarker + * @author Eric Lafortune + */ +public class SimpleEnumArrayPropagator +extends SimplifiedVisitor +implements ClassVisitor, + MemberVisitor +{ + private final ValueFactory valueFactory = new ParticularValueFactory(); + + private Value array; + + + // Implementations for ClassVisitor. + + public void visitProgramClass(ProgramClass programClass) + { + // Update the return value of the "int[] values()" method. + programClass.methodsAccept(new MemberDescriptorFilter("()[I", this)); + } + + + // Implementations for MemberVisitor. + + public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) + { + // Find the array length of the "int[] $VALUES" field. + programClass.fieldsAccept(new MemberDescriptorFilter("[I", this)); + + if (array != null) + { + // Set the array value with the found array length. We can't use + // the original array, because its elements might get overwritten. + Value propagatedArray = + valueFactory.createArrayReferenceValue("I", + null, + array.referenceValue().arrayLength( + valueFactory)); + + setMethodReturnValue(programMethod, propagatedArray); + + array = null; + } + } + + public void visitProgramField(ProgramClass programClass, ProgramField programField) + { + array = StoringInvocationUnit.getFieldValue(programField); + } + + + // Small utility methods. + + private static void setMethodReturnValue(Method method, Value value) + { + MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method); + if (info != null) + { + info.setReturnValue(value); + } + } +} diff --git a/src/proguard/optimize/evaluation/SimpleEnumClassChecker.java b/src/proguard/optimize/evaluation/SimpleEnumClassChecker.java new file mode 100644 index 0000000..1bd5008 --- /dev/null +++ b/src/proguard/optimize/evaluation/SimpleEnumClassChecker.java @@ -0,0 +1,74 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.evaluation; + +import proguard.classfile.*; +import proguard.classfile.visitor.*; +import proguard.optimize.info.SimpleEnumMarker; + +/** + * This ClassVisitor marks all program classes that it visits as simple enums, + * if their methods qualify. + * + * @author Eric Lafortune + */ +public class SimpleEnumClassChecker +implements ClassVisitor +{ + //* + private static final boolean DEBUG = false; + /*/ + private static boolean DEBUG = System.getProperty("enum") != null; + //*/ + + + private final SimpleEnumMarker simpleEnumMarker = new SimpleEnumMarker(true); + private final MemberVisitor virtualMethodChecker = new MemberAccessFilter(0, + ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC, + new MemberToClassVisitor( + new SimpleEnumMarker(false))); + + + // Implementations for ClassVisitor. + + public void visitLibraryClass(LibraryClass libraryClass) {} + + public void visitProgramClass(ProgramClass programClass) + { + // Does the class have the simple enum constructor? + if (programClass.findMethod(ClassConstants.METHOD_NAME_INIT, + ClassConstants.METHOD_TYPE_INIT_ENUM) != null) + { + if (DEBUG) + { + System.out.println("SimpleEnumClassChecker: ["+programClass.getName()+"] is a candidate simple enum, without extra fields"); + } + + // Mark it. + simpleEnumMarker.visitProgramClass(programClass); + + // However, unmark it again if it has any non-private, non-static + // methods. + programClass.methodsAccept(virtualMethodChecker); + } + } +}
\ No newline at end of file diff --git a/src/proguard/optimize/evaluation/SimpleEnumClassSimplifier.java b/src/proguard/optimize/evaluation/SimpleEnumClassSimplifier.java new file mode 100644 index 0000000..33f775f --- /dev/null +++ b/src/proguard/optimize/evaluation/SimpleEnumClassSimplifier.java @@ -0,0 +1,164 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.evaluation; + +import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.*; +import proguard.classfile.constant.*; +import proguard.classfile.editor.*; +import proguard.classfile.instruction.*; +import proguard.classfile.instruction.visitor.InstructionVisitor; +import proguard.classfile.util.SimplifiedVisitor; +import proguard.classfile.visitor.*; +import proguard.optimize.info.SimpleEnumMarker; +import proguard.optimize.peephole.*; + +/** + * This ClassVisitor simplifies the classes that it visits to simple enums. + * + * @see SimpleEnumMarker + * @see MemberReferenceFixer + * @author Eric Lafortune + */ +public class SimpleEnumClassSimplifier +extends SimplifiedVisitor +implements ClassVisitor, + AttributeVisitor, + InstructionVisitor +{ + //* + private static final boolean DEBUG = false; + /*/ + private static boolean DEBUG = System.getProperty("enum") != null; + //*/ + + + private static final int ENUM_CLASS_NAME = InstructionSequenceReplacer.A; + private static final int ENUM_TYPE_NAME = InstructionSequenceReplacer.B; + private static final int ENUM_CONSTANT_NAME = InstructionSequenceReplacer.X; + private static final int ENUM_CONSTANT_ORDINAL = InstructionSequenceReplacer.Y; + private static final int ENUM_CONSTANT_FIELD_NAME = InstructionSequenceReplacer.Z; + + private static final int STRING_ENUM_CONSTANT_NAME = 0; + + private static final int METHOD_ENUM_INIT = 1; + private static final int FIELD_ENUM_CONSTANT = 2; + + private static final int CLASS_ENUM = 3; + + private static final int NAME_AND_TYPE_ENUM_INIT = 4; + private static final int NAME_AND_TYPE_ENUM_CONSTANT = 5; + + private static final int UTF8_INIT = 6; + private static final int UTF8_STRING_I = 7; + + + private static final Constant[] CONSTANTS = new Constant[] + { + new StringConstant(ENUM_CONSTANT_NAME, null, null), + + new MethodrefConstant(CLASS_ENUM, NAME_AND_TYPE_ENUM_INIT, null, null), + new FieldrefConstant( CLASS_ENUM, NAME_AND_TYPE_ENUM_CONSTANT, null, null), + + new ClassConstant(ENUM_CLASS_NAME, null), + + new NameAndTypeConstant(UTF8_INIT, UTF8_STRING_I), + new NameAndTypeConstant(ENUM_CONSTANT_FIELD_NAME, ENUM_TYPE_NAME), + + new Utf8Constant(ClassConstants.METHOD_NAME_INIT), + new Utf8Constant(ClassConstants.METHOD_TYPE_INIT_ENUM), + }; + + private static final Instruction[] INSTRUCTIONS = new Instruction[] + { + new ConstantInstruction(InstructionConstants.OP_NEW, CLASS_ENUM), + new SimpleInstruction(InstructionConstants.OP_DUP), + new ConstantInstruction(InstructionConstants.OP_LDC, STRING_ENUM_CONSTANT_NAME), + new SimpleInstruction(InstructionConstants.OP_ICONST_0, ENUM_CONSTANT_ORDINAL), + new ConstantInstruction(InstructionConstants.OP_INVOKESPECIAL, METHOD_ENUM_INIT), + }; + + private static final Instruction[] REPLACEMENT_INSTRUCTIONS = new Instruction[] + { + new SimpleInstruction(InstructionConstants.OP_SIPUSH, ENUM_CONSTANT_ORDINAL), + new SimpleInstruction(InstructionConstants.OP_ICONST_1), + new SimpleInstruction(InstructionConstants.OP_IADD), + }; + + + private final CodeAttributeEditor codeAttributeEditor = + new CodeAttributeEditor(true, true); + + private final InstructionSequenceReplacer instructionSequenceReplacer = + new InstructionSequenceReplacer(CONSTANTS, + INSTRUCTIONS, + REPLACEMENT_INSTRUCTIONS, + null, + codeAttributeEditor); + + private final MemberVisitor initializerSimplifier = new AllAttributeVisitor(this); + + + // Implementations for ClassVisitor. + + public void visitProgramClass(ProgramClass programClass) + { + if (DEBUG) + { + System.out.println("SimpleEnumClassSimplifier: ["+programClass.getName()+"]"); + } + + // Unmark the class as an enum. + programClass.u2accessFlags &= ~ClassConstants.ACC_ENUM; + + // Remove the valueOf method, if present. + Method valueOfMethod = + programClass.findMethod(ClassConstants.METHOD_NAME_VALUEOF, null); + if (valueOfMethod != null) + { + new ClassEditor(programClass).removeMethod(valueOfMethod); + } + + // Simplify the static initializer. + programClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT, + ClassConstants.METHOD_TYPE_CLINIT, + initializerSimplifier); + } + + + // Implementations for AttributeVisitor. + + public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + + + public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) + { + // Set up the code attribute editor. + codeAttributeEditor.reset(codeAttribute.u4codeLength); + + // Find the peephole changes. + codeAttribute.instructionsAccept(clazz, method, instructionSequenceReplacer); + + // Apply the peephole changes. + codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute); + } +} diff --git a/src/proguard/optimize/evaluation/SimpleEnumDescriptorSimplifier.java b/src/proguard/optimize/evaluation/SimpleEnumDescriptorSimplifier.java new file mode 100644 index 0000000..f1323ea --- /dev/null +++ b/src/proguard/optimize/evaluation/SimpleEnumDescriptorSimplifier.java @@ -0,0 +1,583 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.evaluation; + +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.editor.*; +import proguard.classfile.instruction.visitor.InstructionVisitor; +import proguard.classfile.util.*; +import proguard.classfile.visitor.*; +import proguard.optimize.info.*; + +/** + * This ClassVisitor simplifies the descriptors that contain simple enums in + * the program classes that it visits. + * + * @see SimpleEnumMarker + * @see MemberReferenceFixer + * @author Eric Lafortune + */ +public class SimpleEnumDescriptorSimplifier +extends SimplifiedVisitor +implements ClassVisitor, + ConstantVisitor, + MemberVisitor, + AttributeVisitor, + LocalVariableInfoVisitor, + LocalVariableTypeInfoVisitor +{ + //* + private static final boolean DEBUG = false; + /*/ + private static boolean DEBUG = System.getProperty("enum") != null; + //*/ + + + // Implementations for ClassVisitor. + + public void visitProgramClass(ProgramClass programClass) + { + if (DEBUG) + { + System.out.println("SimpleEnumDescriptorSimplifier: "+programClass.getName()); + } + + // Simplify the class members. + programClass.fieldsAccept(this); + programClass.methodsAccept(this); + + // Simplify the attributes. + //programClass.attributesAccept(this); + + // Simplify the simple enum array constants. + programClass.constantPoolEntriesAccept(this); + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitStringConstant(Clazz clazz, StringConstant stringConstant) + { + // Does the constant refer to a simple enum type? + Clazz referencedClass = stringConstant.referencedClass; + if (isSimpleEnum(referencedClass)) + { + // Is it an array type? + String name = stringConstant.getString(clazz); + if (ClassUtil.isInternalArrayType(name)) + { + // Update the type. + ConstantPoolEditor constantPoolEditor = + new ConstantPoolEditor((ProgramClass)clazz); + + String newName = simplifyDescriptor(name, referencedClass); + + stringConstant.u2stringIndex = + constantPoolEditor.addUtf8Constant(newName); + + // Clear the referenced class. + stringConstant.referencedClass = null; + } + } + } + + + public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + { + // Update the descriptor if it has any simple enum classes. + String descriptor = invokeDynamicConstant.getType(clazz); + String newDescriptor = simplifyDescriptor(descriptor, invokeDynamicConstant.referencedClasses); + + if (!descriptor.equals(newDescriptor)) + { + // Update the descriptor. + ConstantPoolEditor constantPoolEditor = + new ConstantPoolEditor((ProgramClass)clazz); + + invokeDynamicConstant.u2nameAndTypeIndex = + constantPoolEditor.addNameAndTypeConstant(invokeDynamicConstant.getName(clazz), + newDescriptor); + + // Update the referenced classes. + invokeDynamicConstant.referencedClasses = + simplifyReferencedClasses(descriptor, invokeDynamicConstant.referencedClasses); + } + } + + + public void visitClassConstant(Clazz clazz, ClassConstant classConstant) + { + // Does the constant refer to a simple enum type? + Clazz referencedClass = classConstant.referencedClass; + if (isSimpleEnum(referencedClass)) + { + // Is it an array type? + String name = classConstant.getName(clazz); + if (ClassUtil.isInternalArrayType(name)) + { + // Update the type. + ConstantPoolEditor constantPoolEditor = + new ConstantPoolEditor((ProgramClass)clazz); + + String newName = simplifyDescriptor(name, referencedClass); + + classConstant.u2nameIndex = + constantPoolEditor.addUtf8Constant(newName); + + // Clear the referenced class. + classConstant.referencedClass = null; + } + } + } + + + // Implementations for MemberVisitor. + + public void visitProgramField(ProgramClass programClass, ProgramField programField) + { + // Update the descriptor if it has a simple enum class. + String descriptor = programField.getDescriptor(programClass); + String newDescriptor = simplifyDescriptor(descriptor, programField.referencedClass); + + if (!descriptor.equals(newDescriptor)) + { + String name = programField.getName(programClass); + String newName = name + ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode())); + + if (DEBUG) + { + System.out.println("SimpleEnumDescriptorSimplifier: ["+programClass.getName()+"."+name+" "+descriptor + "] -> ["+newName+" "+newDescriptor+"]"); + } + + ConstantPoolEditor constantPoolEditor = + new ConstantPoolEditor(programClass); + + // Update the name. + programField.u2nameIndex = + constantPoolEditor.addUtf8Constant(newName); + + // Update the descriptor itself. + programField.u2descriptorIndex = + constantPoolEditor.addUtf8Constant(newDescriptor); + + // Clear the referenced class. + programField.referencedClass = null; + + // Clear the field value. + FieldOptimizationInfo fieldOptimizationInfo = + FieldOptimizationInfo.getFieldOptimizationInfo(programField); + if (fieldOptimizationInfo != null) + { + fieldOptimizationInfo.resetValue(programClass, programField); + } + + // Simplify the signature. + programField.attributesAccept(programClass, this); + } + } + + + public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) + { +// // Skip the valueOf method. +// if (programMethod.getName(programClass).equals(ClassConstants.METHOD_NAME_VALUEOF)) +// { +// return; +// } + + // Simplify the code, the signature, and the parameter annotations, + // before simplifying the descriptor. + programMethod.attributesAccept(programClass, this); + + // Update the descriptor if it has any simple enum classes. + String descriptor = programMethod.getDescriptor(programClass); + String newDescriptor = simplifyDescriptor(descriptor, programMethod.referencedClasses); + + if (!descriptor.equals(newDescriptor)) + { + String name = programMethod.getName(programClass); + String newName = name; + + // Append a code, if the method isn't a class instance initializer. + if (!name.equals(ClassConstants.METHOD_NAME_INIT)) + { + newName += ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode())); + } + + if (DEBUG) + { + System.out.println("SimpleEnumDescriptorSimplifier: ["+programClass.getName()+"."+name+descriptor+"] -> ["+newName+newDescriptor+"]"); + } + + ConstantPoolEditor constantPoolEditor = + new ConstantPoolEditor(programClass); + + // Update the name, if necessary. + if (!newName.equals(name)) + { + programMethod.u2nameIndex = + constantPoolEditor.addUtf8Constant(newName); + } + + // Update the descriptor itself. + programMethod.u2descriptorIndex = + constantPoolEditor.addUtf8Constant(newDescriptor); + + // Update the referenced classes. + programMethod.referencedClasses = + simplifyReferencedClasses(descriptor, programMethod.referencedClasses); + } + } + + + // Implementations for AttributeVisitor. + + public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + + + public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) + { + // Simplify the local variable descriptors. + codeAttribute.attributesAccept(clazz, method, this); + } + + + public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) + { + // Change the references of the local variables. + localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); + } + + + public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) + { + // Change the references of the local variables. + localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); + } + + + public void visitSignatureAttribute(Clazz clazz, Field field, SignatureAttribute signatureAttribute) + { + // We're only looking at the base type for now. + if (signatureAttribute.referencedClasses != null && + signatureAttribute.referencedClasses.length > 0) + { + // Update the signature if it has any simple enum classes. + String signature = signatureAttribute.getSignature(clazz); + String newSignature = simplifyDescriptor(signature, + signatureAttribute.referencedClasses[0]); + + if (!signature.equals(newSignature)) + { + // Update the signature. + signatureAttribute.u2signatureIndex = + new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature); + + // Clear the referenced class. + signatureAttribute.referencedClasses[0] = null; + } + } + } + + + public void visitSignatureAttribute(Clazz clazz, Method method, SignatureAttribute signatureAttribute) + { + // Compute the new signature. + String signature = signatureAttribute.getSignature(clazz); + String newSignature = simplifyDescriptor(signature, + signatureAttribute.referencedClasses); + + if (!signature.equals(newSignature)) + { + // Update the signature. + signatureAttribute.u2signatureIndex = + new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature); + } + } + + + // Implementations for LocalVariableInfoVisitor. + + public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) + { + // Update the descriptor if it has a simple enum class. + String descriptor = localVariableInfo.getDescriptor(clazz); + String newDescriptor = simplifyDescriptor(descriptor, localVariableInfo.referencedClass); + + if (!descriptor.equals(newDescriptor)) + { + // Update the descriptor. + localVariableInfo.u2descriptorIndex = + new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newDescriptor); + + // Clear the referenced class. + localVariableInfo.referencedClass = null; + } + } + + + // Implementations for LocalVariableTypeInfoVisitor. + + public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) + { + // We're only looking at the base type for now. + if (localVariableTypeInfo.referencedClasses != null && + localVariableTypeInfo.referencedClasses.length > 0) + { + // Update the signature if it has any simple enum classes. + String signature = localVariableTypeInfo.getSignature(clazz); + String newSignature = simplifyDescriptor(signature, + localVariableTypeInfo.referencedClasses[0]); + + if (!signature.equals(newSignature)) + { + // Update the signature. + localVariableTypeInfo.u2signatureIndex = + new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature); + + // Clear the referenced class. + localVariableTypeInfo.referencedClasses[0] = null; + } + } + } + + + // Small utility methods. + + /** + * Returns the descriptor with simplified enum type. + */ + private String simplifyDescriptor(String descriptor, + Clazz referencedClass) + { + return isSimpleEnum(referencedClass) ? + descriptor.substring(0, ClassUtil.internalArrayTypeDimensionCount(descriptor)) + ClassConstants.TYPE_INT : + descriptor; + } + + + /** + * Returns the descriptor with simplified enum types. + */ + private String simplifyDescriptor(String descriptor, + Clazz[] referencedClasses) + { + if (referencedClasses != null) + { + InternalTypeEnumeration internalTypeEnumeration = + new InternalTypeEnumeration(descriptor); + + int referencedClassIndex = 0; + + StringBuffer newDescriptorBuffer = + new StringBuffer(descriptor.length()); + + // Go over the formal type parameters. + { + // Consider the classes referenced by this formal type + // parameter. + String type = internalTypeEnumeration.formalTypeParameters(); + int count = new DescriptorClassEnumeration(type).classCount(); + + // Replace simple enum types. + for (int counter = 0; counter < count; counter++) + { + Clazz referencedClass = + referencedClasses[referencedClassIndex++]; + + if (isSimpleEnum(referencedClass)) + { + // Let's replace the simple enum type by + // java.lang.Integer. + type = + type.substring(0, ClassUtil.internalArrayTypeDimensionCount(type)) + + ClassConstants.NAME_JAVA_LANG_INTEGER; + } + } + + newDescriptorBuffer.append(type); + } + + newDescriptorBuffer.append(ClassConstants.METHOD_ARGUMENTS_OPEN); + + // Go over the parameters. + while (internalTypeEnumeration.hasMoreTypes()) + { + // Consider the classes referenced by this parameter type. + String type = internalTypeEnumeration.nextType(); + int count = new DescriptorClassEnumeration(type).classCount(); + + // Replace simple enum types. + for (int counter = 0; counter < count; counter++) + { + Clazz referencedClass = + referencedClasses[referencedClassIndex++]; + + if (isSimpleEnum(referencedClass)) + { + type = + type.substring(0, ClassUtil.internalArrayTypeDimensionCount(type)) + + ClassConstants.TYPE_INT; + } + } + + newDescriptorBuffer.append(type); + } + + newDescriptorBuffer.append(ClassConstants.METHOD_ARGUMENTS_CLOSE); + + // Go over the return value. + { + String type = internalTypeEnumeration.returnType(); + int count = new DescriptorClassEnumeration(type).classCount(); + + // Replace simple enum types. + for (int counter = 0; counter < count; counter++) + { + Clazz referencedClass = + referencedClasses[referencedClassIndex++]; + + if (isSimpleEnum(referencedClass)) + { + type = + type.substring(0, ClassUtil.internalArrayTypeDimensionCount(type)) + + ClassConstants.TYPE_INT; + } + } + + newDescriptorBuffer.append(type); + } + + descriptor = newDescriptorBuffer.toString(); + } + + return descriptor; + } + + + /** + * Returns the simplified and shrunk array of referenced classes for the + * given descriptor. + */ + private Clazz[] simplifyReferencedClasses(String descriptor, + Clazz[] referencedClasses) + { + if (referencedClasses != null) + { + InternalTypeEnumeration internalTypeEnumeration = + new InternalTypeEnumeration(descriptor); + + int referencedClassIndex = 0; + int newReferencedClassIndex = 0; + + // Go over the formal type parameters. + { + String type = internalTypeEnumeration.formalTypeParameters(); + int count = new DescriptorClassEnumeration(type).classCount(); + + // Clear all non-simple enum classes + // (now java.lang.Integer). + for (int counter = 0; counter < count; counter++) + { + Clazz referencedClass = + referencedClasses[referencedClassIndex++]; + + referencedClasses[newReferencedClassIndex++] = + isSimpleEnum(referencedClass) ? null : referencedClass; + } + } + + // Go over the parameters. + while (internalTypeEnumeration.hasMoreTypes()) + { + // Consider the classes referenced by this parameter type. + String type = internalTypeEnumeration.nextType(); + int count = new DescriptorClassEnumeration(type).classCount(); + + // Copy all non-simple enum classes. + for (int counter = 0; counter < count; counter++) + { + Clazz referencedClass = + referencedClasses[referencedClassIndex++]; + + if (!isSimpleEnum(referencedClass)) + { + referencedClasses[newReferencedClassIndex++] = + referencedClass; + } + } + } + + // Go over the return type. + { + String type = internalTypeEnumeration.returnType(); + int count = new DescriptorClassEnumeration(type).classCount(); + + // Copy all non-simple enum classes. + for (int counter = 0; counter < count; counter++) + { + Clazz referencedClass = + referencedClasses[referencedClassIndex++]; + + if (!isSimpleEnum(referencedClass)) + { + referencedClasses[newReferencedClassIndex++] = + referencedClass; + } + } + } + + // Shrink the array to the proper size. + if (newReferencedClassIndex == 0) + { + referencedClasses = null; + } + else if (newReferencedClassIndex < referencedClassIndex) + { + Clazz[] newReferencedClasses = new Clazz[newReferencedClassIndex]; + System.arraycopy(referencedClasses, 0, + newReferencedClasses, 0, + newReferencedClassIndex); + + referencedClasses = newReferencedClasses; + } + } + + return referencedClasses; + } + + + /** + * Returns whether the given class is not null and a simple enum class. + */ + private boolean isSimpleEnum(Clazz clazz) + { + return clazz != null && + SimpleEnumMarker.isSimpleEnum(clazz); + } +} diff --git a/src/proguard/optimize/evaluation/SimpleEnumUseChecker.java b/src/proguard/optimize/evaluation/SimpleEnumUseChecker.java new file mode 100644 index 0000000..b748c68 --- /dev/null +++ b/src/proguard/optimize/evaluation/SimpleEnumUseChecker.java @@ -0,0 +1,760 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.evaluation; + +import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.*; +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.*; +import proguard.classfile.visitor.*; +import proguard.evaluation.*; +import proguard.evaluation.value.*; +import proguard.optimize.info.SimpleEnumMarker; + +/** + * This ClassVisitor marks enums that can't be simplified due to the way they + * are used in the classes that it visits. + * + * @see SimpleEnumMarker + * @author Eric Lafortune + */ +public class SimpleEnumUseChecker +extends SimplifiedVisitor +implements ClassVisitor, + MemberVisitor, + AttributeVisitor, + InstructionVisitor, + ConstantVisitor, + ParameterVisitor +{ + //* + private static final boolean DEBUG = false; + /*/ + private static boolean DEBUG = System.getProperty("enum") != null; + //*/ + + private final PartialEvaluator partialEvaluator; + private final MemberVisitor methodCodeChecker = new AllAttributeVisitor(this); + private final ConstantVisitor invokedMethodChecker = new ReferencedMemberVisitor(this); + private final ConstantVisitor parameterChecker = new ReferencedMemberVisitor(new AllParameterVisitor(this)); + private final ClassVisitor complexEnumMarker = new SimpleEnumMarker(false); + private final ReferencedClassVisitor referencedComplexEnumMarker = new ReferencedClassVisitor(complexEnumMarker); + + + // Fields acting as parameters and return values for the visitor methods. + private int invocationOffset; + + + /** + * Creates a new SimpleEnumUseSimplifier. + */ + public SimpleEnumUseChecker() + { + this(new PartialEvaluator()); + } + + + /** + * Creates a new SimpleEnumUseChecker. + * @param partialEvaluator the partial evaluator that will execute the code + * and provide information about the results. + */ + public SimpleEnumUseChecker(PartialEvaluator partialEvaluator) + { + this.partialEvaluator = partialEvaluator; + } + + + // Implementations for ClassVisitor. + + public void visitProgramClass(ProgramClass programClass) + { + if ((programClass.getAccessFlags() & ClassConstants.ACC_ANNOTATTION) != 0) + { + // Unmark the simple enum classes in annotations. + programClass.methodsAccept(referencedComplexEnumMarker); + } + else + { + // Unmark the simple enum classes that are used in a complex way. + programClass.methodsAccept(methodCodeChecker); + } + } + + + // Implementations for AttributeVisitor. + + public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + + + public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) + { + // Evaluate the method. + partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute); + + int codeLength = codeAttribute.u4codeLength; + + // Check all traced instructions. + for (int offset = 0; offset < codeLength; offset++) + { + if (partialEvaluator.isTraced(offset)) + { + Instruction instruction = InstructionFactory.create(codeAttribute.code, + offset); + + instruction.accept(clazz, method, codeAttribute, offset, this); + + // Check generalized stacks and variables at branch targets. + if (partialEvaluator.isBranchOrExceptionTarget(offset)) + { + checkMixedStackEntriesBefore(offset); + + checkMixedVariablesBefore(offset); + } + } + } + } + + + // Implementations for InstructionVisitor. + + public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) + { + switch (simpleInstruction.opcode) + { + case InstructionConstants.OP_AASTORE: + { + // Check if the instruction is storing a simple enum in a + // more general array. + if (!isPoppingSimpleEnumType(offset, 2)) + { + if (DEBUG) + { + if (isPoppingSimpleEnumType(offset)) + { + System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] stores enum ["+ + partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] in more general array ["+ + partialEvaluator.getStackBefore(offset).getTop(2).referenceValue().getType()+"]"); + } + } + + markPoppedComplexEnumType(offset); + } + break; + } + case InstructionConstants.OP_ARETURN: + { + // Check if the instruction is returning a simple enum as a + // more general type. + if (!isReturningSimpleEnumType(clazz, method)) + { + if (DEBUG) + { + if (isPoppingSimpleEnumType(offset)) + { + System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] returns enum [" + + partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] as more general type"); + } + } + + markPoppedComplexEnumType(offset); + } + break; + } + case InstructionConstants.OP_MONITORENTER: + case InstructionConstants.OP_MONITOREXIT: + { + // Make sure the popped type is not a simple enum type. + if (DEBUG) + { + if (isPoppingSimpleEnumType(offset)) + { + System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] uses enum ["+ + partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] as monitor"); + } + } + + markPoppedComplexEnumType(offset); + + break; + } + } + } + + + public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) + { + } + + + public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) + { + switch (constantInstruction.opcode) + { + case InstructionConstants.OP_PUTSTATIC: + case InstructionConstants.OP_PUTFIELD: + { + // Check if the instruction is generalizing a simple enum to a + // different type. + invocationOffset = offset; + clazz.constantPoolEntryAccept(constantInstruction.constantIndex, + parameterChecker); + break; + } + case InstructionConstants.OP_INVOKEVIRTUAL: + { + // Check if the instruction is calling a simple enum. + String invokedMethodName = + clazz.getRefName(constantInstruction.constantIndex); + String invokedMethodType = + clazz.getRefType(constantInstruction.constantIndex); + int stackEntryIndex = + ClassUtil.internalMethodParameterSize(invokedMethodType); + if (isPoppingSimpleEnumType(offset, stackEntryIndex) && + !isSupportedMethod(invokedMethodName, + invokedMethodType)) + { + if (DEBUG) + { + System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] calls ["+partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue().getType()+"."+invokedMethodName+"]"); + } + + markPoppedComplexEnumType(offset, stackEntryIndex); + } + + // Check if any of the parameters is generalizing a simple + // enum to a different type. + invocationOffset = offset; + clazz.constantPoolEntryAccept(constantInstruction.constantIndex, + parameterChecker); + break; + } + case InstructionConstants.OP_INVOKESPECIAL: + case InstructionConstants.OP_INVOKESTATIC: + case InstructionConstants.OP_INVOKEINTERFACE: + { + // Check if it is calling a method that we can't simplify. + clazz.constantPoolEntryAccept(constantInstruction.constantIndex, + invokedMethodChecker); + + // Check if any of the parameters is generalizing a simple + // enum to a different type. + invocationOffset = offset; + clazz.constantPoolEntryAccept(constantInstruction.constantIndex, + parameterChecker); + break; + } + case InstructionConstants.OP_CHECKCAST: + case InstructionConstants.OP_INSTANCEOF: + { + // Check if the instruction is popping a different type. + if (!isPoppingExpectedType(offset, + clazz, + constantInstruction.constantIndex)) + { + if (DEBUG) + { + if (isPoppingSimpleEnumType(offset)) + { + System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] is casting or checking ["+ + partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] as ["+ + clazz.getClassName(constantInstruction.constantIndex)+"]"); + } + } + + // Make sure the popped type is not a simple enum type. + markPoppedComplexEnumType(offset); + + // Make sure the checked type is not a simple enum type. + // We're somewhat arbitrarily skipping casts in static + // methods of simple enum classes, because they do occur + // in values() and valueOf(String), without obstructing + // simplification. + if (!isSimpleEnum(clazz) || + (method.getAccessFlags() & ClassConstants.ACC_STATIC) == 0 || + constantInstruction.opcode != InstructionConstants.OP_CHECKCAST) + { + if (DEBUG) + { + if (isSimpleEnum(((ClassConstant)((ProgramClass)clazz).getConstant(constantInstruction.constantIndex)).referencedClass)) + { + System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] is casting or checking ["+ + partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] as ["+ + clazz.getClassName(constantInstruction.constantIndex)+"]"); + } + } + + markConstantComplexEnumType(clazz, constantInstruction.constantIndex); + } + } + break; + } + } + } + + + public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) + { + switch (branchInstruction.opcode) + { + case InstructionConstants.OP_IFACMPEQ: + case InstructionConstants.OP_IFACMPNE: + { + // Check if the instruction is comparing different types. + if (!isPoppingIdenticalTypes(offset, 0, 1)) + { + if (DEBUG) + { + if (isPoppingSimpleEnumType(offset, 0)) + { + System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] compares ["+partialEvaluator.getStackBefore(offset).getTop(0).referenceValue().getType()+"] to plain type"); + } + + if (isPoppingSimpleEnumType(offset, 1)) + { + System.out.println("SimpleEnumUseChecker: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] compares ["+partialEvaluator.getStackBefore(offset).getTop(1).referenceValue().getType()+"] to plain type"); + } + } + + // Make sure the first popped type is not a simple enum type. + markPoppedComplexEnumType(offset, 0); + + // Make sure the second popped type is not a simple enum type. + markPoppedComplexEnumType(offset, 1); + } + break; + } + } + } + + + public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction) + { + } + + + // Implementations for MemberVisitor. + + public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) {} + + + public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) + { + if (isSimpleEnum(programClass) && + isUnsupportedMethod(programMethod.getName(programClass), + programMethod.getDescriptor(programClass))) + { + if (DEBUG) + { + System.out.println("SimpleEnumUseChecker: invocation of ["+programClass.getName()+"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"]"); + } + + complexEnumMarker.visitProgramClass(programClass); + } + } + + + // Implementations for ParameterVisitor. + + public void visitParameter(Clazz clazz, Member member, int parameterIndex, int parameterCount, int parameterOffset, int parameterSize, String parameterType, Clazz referencedClass) + { + // Check if the parameter is passing a simple enum as a more general + // type. + int stackEntryIndex = parameterSize - parameterOffset - 1; + if (ClassUtil.isInternalClassType(parameterType) && + !isPoppingExpectedType(invocationOffset, stackEntryIndex, + ClassUtil.isInternalArrayType(parameterType) ? + parameterType : + ClassUtil.internalClassNameFromClassType(parameterType))) + { + if (DEBUG) + { + ReferenceValue poppedValue = + partialEvaluator.getStackBefore(invocationOffset).getTop(stackEntryIndex).referenceValue(); + if (isSimpleEnumType(poppedValue)) + { + System.out.println("SimpleEnumUseChecker: ["+poppedValue.getType()+"] "+ + (member instanceof Field ? + ("is stored as more general type ["+parameterType+"] in field ["+clazz.getName()+"."+member.getName(clazz)+"]") : + ("is passed as more general argument #"+parameterIndex+" ["+parameterType+"] to ["+clazz.getName()+"."+member.getName(clazz)+"]"))); + } + } + + // Make sure the popped type is not a simple enum type. + markPoppedComplexEnumType(invocationOffset, stackEntryIndex); + } + } + + + // Small utility methods. + + /** + * Returns whether the specified enum method is supported for simple enums. + */ + private boolean isSupportedMethod(String name, String type) + { + return + name.equals(ClassConstants.METHOD_NAME_ORDINAL) && + type.equals(ClassConstants.METHOD_TYPE_ORDINAL) || + + name.equals(ClassConstants.METHOD_NAME_CLONE) && + type.equals(ClassConstants.METHOD_TYPE_CLONE); + } + + + /** + * Returns whether the specified enum method is unsupported for simple enums. + */ + private boolean isUnsupportedMethod(String name, String type) + { + return + name.equals(ClassConstants.METHOD_NAME_VALUEOF); + } + + + /** + * Unmarks simple enum classes that are mixed with incompatible reference + * types in the stack before the given instruction offset. + */ + private void checkMixedStackEntriesBefore(int offset) + { + TracedStack stackBefore = partialEvaluator.getStackBefore(offset); + + // Check all stack entries. + int stackSize = stackBefore.size(); + + for (int stackEntryIndex = 0; stackEntryIndex < stackSize; stackEntryIndex++) + { + // Check reference entries. + Value stackEntry = stackBefore.getBottom(stackEntryIndex); + if (stackEntry.computationalType() == Value.TYPE_REFERENCE) + { + // Check reference entries with multiple producers. + InstructionOffsetValue producerOffsets = + stackBefore.getBottomActualProducerValue(stackEntryIndex).instructionOffsetValue(); + + int producerCount = producerOffsets.instructionOffsetCount(); + if (producerCount > 1) + { + // Is the consumed stack entry not a simple enum? + ReferenceValue consumedStackEntry = + stackEntry.referenceValue(); + + if (!isSimpleEnumType(consumedStackEntry)) + { + // Check all producers. + for (int producerIndex = 0; producerIndex < producerCount; producerIndex++) + { + int producerOffset = + producerOffsets.instructionOffset(producerIndex); + + if (producerOffset >= 0) + { + if (DEBUG) + { + ReferenceValue producedValue = + partialEvaluator.getStackAfter(producerOffset).getTop(0).referenceValue(); + if (isSimpleEnumType(producedValue)) + { + System.out.println("SimpleEnumUseChecker: ["+producedValue.getType()+"] mixed with general type on stack"); + } + } + + // Make sure the produced stack entry isn't a + // simple enum either. + markPushedComplexEnumType(producerOffset); + } + } + } + } + } + } + } + + + /** + * Unmarks simple enum classes that are mixed with incompatible reference + * types in the variables before the given instruction offset. + */ + private void checkMixedVariablesBefore(int offset) + { + TracedVariables variablesBefore = + partialEvaluator.getVariablesBefore(offset); + + // Check all variables. + int variablesSize = variablesBefore.size(); + + for (int variableIndex = 0; variableIndex < variablesSize; variableIndex++) + { + // Check reference variables. + Value variable = variablesBefore.getValue(variableIndex); + if (variable != null && + variable.computationalType() == Value.TYPE_REFERENCE) + { + // Check reference variables with multiple producers. + InstructionOffsetValue producerOffsets = + variablesBefore.getProducerValue(variableIndex).instructionOffsetValue(); + + int producerCount = producerOffsets.instructionOffsetCount(); + if (producerCount > 1) + { + // Is the consumed variable not a simple enum? + ReferenceValue consumedVariable = + variable.referenceValue(); + + if (!isSimpleEnumType(consumedVariable)) + { + // Check all producers. + for (int producerIndex = 0; producerIndex < producerCount; producerIndex++) + { + int producerOffset = + producerOffsets.instructionOffset(producerIndex); + + if (producerOffset >= 0) + { + if (DEBUG) + { + ReferenceValue producedValue = + partialEvaluator.getVariablesAfter(producerOffset).getValue(variableIndex).referenceValue(); + if (isSimpleEnumType(producedValue)) + { + System.out.println("SimpleEnumUseChecker: ["+producedValue.getType()+"] mixed with general type in variables"); + } + } + + // Make sure the stored variable entry isn't a + // simple enum either. + markStoredComplexEnumType(producerOffset, variableIndex); + } + } + } + } + } + } + } + + + /** + * Returns whether the instruction at the given offset is popping two + * identical reference types. + */ + private boolean isPoppingIdenticalTypes(int offset, + int stackEntryIndex1, + int stackEntryIndex2) + { + TracedStack stackBefore = partialEvaluator.getStackBefore(offset); + + String type1 = + stackBefore.getTop(stackEntryIndex1).referenceValue().getType(); + String type2 = + stackBefore.getTop(stackEntryIndex2).referenceValue().getType(); + + return type1 == null ? type2 == null : type1.equals(type2); + } + + + /** + * Returns whether the instruction at the given offset is popping exactly + * the reference type of the specified class constant. + */ + private boolean isPoppingExpectedType(int offset, + Clazz clazz, + int constantIndex) + { + return isPoppingExpectedType(offset, 0, clazz, constantIndex); + } + + + /** + * Returns whether the instruction at the given offset is popping exactly + * the reference type of the specified class constant. + */ + private boolean isPoppingExpectedType(int offset, + int stackEntryIndex, + Clazz clazz, + int constantIndex) + { + return isPoppingExpectedType(offset, + stackEntryIndex, + clazz.getClassName(constantIndex)); + } + + + /** + * Returns whether the instruction at the given offset is popping exactly + * the given reference type. + */ + private boolean isPoppingExpectedType(int offset, + int stackEntryIndex, + String expectedType) + { + TracedStack stackBefore = partialEvaluator.getStackBefore(offset); + + String poppedType = + stackBefore.getTop(stackEntryIndex).referenceValue().getType(); + + return expectedType.equals(poppedType); + } + + + /** + * Returns whether the given method is returning a simple enum type. + * This includes simple enum arrays. + */ + private boolean isReturningSimpleEnumType(Clazz clazz, Method method) + { + String descriptor = method.getDescriptor(clazz); + String returnType = ClassUtil.internalMethodReturnType(descriptor); + + if (ClassUtil.isInternalClassType(returnType)) + { + Clazz[] referencedClasses = + ((ProgramMethod)method).referencedClasses; + + if (referencedClasses != null) + { + int returnedClassIndex = + new DescriptorClassEnumeration(descriptor).classCount() - 1; + + Clazz returnedClass = referencedClasses[returnedClassIndex]; + + return isSimpleEnum(returnedClass); + } + } + + return false; + } + + + /** + * Returns whether the instruction at the given offset is popping a type + * with a simple enum class. This includes simple enum arrays. + */ + private boolean isPoppingSimpleEnumType(int offset) + { + return isPoppingSimpleEnumType(offset, 0); + } + + + /** + * Returns whether the instruction at the given offset is popping a type + * with a simple enum class. This includes simple enum arrays. + */ + private boolean isPoppingSimpleEnumType(int offset, int stackEntryIndex) + { + ReferenceValue referenceValue = + partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue(); + + return isSimpleEnumType(referenceValue); + } + + + /** + * Returns whether the given value is a simple enum type. This includes + * simple enum arrays. + */ + private boolean isSimpleEnumType(ReferenceValue referenceValue) + { + return isSimpleEnum(referenceValue.getReferencedClass()); + } + + + /** + * Returns whether the given class is not null and a simple enum class. + */ + private boolean isSimpleEnum(Clazz clazz) + { + return clazz != null && + SimpleEnumMarker.isSimpleEnum(clazz); + } + + + /** + * Marks the enum class of the popped type as complex. + */ + private void markConstantComplexEnumType(Clazz clazz, int constantIndex) + { + clazz.constantPoolEntryAccept(constantIndex, + referencedComplexEnumMarker); + } + + + /** + * Marks the enum class of the popped type as complex. + */ + private void markPoppedComplexEnumType(int offset) + { + markPoppedComplexEnumType(offset, 0); + } + + + /** + * Marks the enum class of the specified popped type as complex. + */ + private void markPoppedComplexEnumType(int offset, int stackEntryIndex) + { + ReferenceValue referenceValue = + partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue(); + + markComplexEnumType(referenceValue); + } + + + /** + * Marks the enum class of the specified pushed type as complex. + */ + private void markPushedComplexEnumType(int offset) + { + ReferenceValue referenceValue = + partialEvaluator.getStackAfter(offset).getTop(0).referenceValue(); + + markComplexEnumType(referenceValue); + } + + + /** + * Marks the enum class of the specified stored type as complex. + */ + private void markStoredComplexEnumType(int offset, int variableIndex) + { + ReferenceValue referenceValue = + partialEvaluator.getVariablesAfter(offset).getValue(variableIndex).referenceValue(); + + markComplexEnumType(referenceValue); + } + + + /** + * Marks the enum class of the specified value as complex. + */ + private void markComplexEnumType(ReferenceValue referenceValue) + { + Clazz clazz = referenceValue.getReferencedClass(); + if (clazz != null) + { + clazz.accept(complexEnumMarker); + } + } +} diff --git a/src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java b/src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java new file mode 100644 index 0000000..b5a2396 --- /dev/null +++ b/src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java @@ -0,0 +1,820 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.evaluation; + +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.*; +import proguard.classfile.instruction.*; +import proguard.classfile.instruction.visitor.InstructionVisitor; +import proguard.classfile.util.*; +import proguard.classfile.visitor.*; +import proguard.evaluation.value.*; +import proguard.optimize.info.SimpleEnumMarker; + +/** + * This AttributeVisitor simplifies the use of enums in the code attributes that + * it visits. + * + * @see SimpleEnumMarker + * @see MemberReferenceFixer + * @author Eric Lafortune + */ +public class SimpleEnumUseSimplifier +extends SimplifiedVisitor +implements AttributeVisitor, + InstructionVisitor, + ConstantVisitor, + ParameterVisitor +{ + //* + private static final boolean DEBUG = false; + /*/ + private static boolean DEBUG = System.getProperty("enum") != null; + //*/ + + private final InstructionVisitor extraInstructionVisitor; + + private final PartialEvaluator partialEvaluator; + private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(true, true); + private final ConstantVisitor nullParameterFixer = new ReferencedMemberVisitor(new AllParameterVisitor(this)); + + // Fields acting as parameters and return values for the visitor methods. + private Clazz invocationClazz; + private Method invocationMethod; + private CodeAttribute invocationCodeAttribute; + private int invocationOffset; + private boolean isSimpleEnum; + + + /** + * Creates a new SimpleEnumUseSimplifier. + */ + public SimpleEnumUseSimplifier() + { + this(new PartialEvaluator(), null); + } + + + /** + * Creates a new SimpleEnumDescriptorSimplifier. + * @param partialEvaluator the partial evaluator that will + * execute the code and provide + * information about the results. + * @param extraInstructionVisitor an optional extra visitor for all + * simplified instructions. + */ + public SimpleEnumUseSimplifier(PartialEvaluator partialEvaluator, + InstructionVisitor extraInstructionVisitor) + { + this.partialEvaluator = partialEvaluator; + this.extraInstructionVisitor = extraInstructionVisitor; + } + + + // Implementations for AttributeVisitor. + + public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + + + public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) + { + if (DEBUG) + { + System.out.println("SimpleEnumUseSimplifier: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)); + } + + // Skip the non-static methods of simple enum classes. + if (SimpleEnumMarker.isSimpleEnum(clazz) && + (method.getAccessFlags() & ClassConstants.ACC_STATIC) == 0) + { + return; + } + + // Evaluate the method. + partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute); + + int codeLength = codeAttribute.u4codeLength; + + // Reset the code changes. + codeAttributeEditor.reset(codeLength); + + // Replace any instructions that can be simplified. + for (int offset = 0; offset < codeLength; offset++) + { + if (partialEvaluator.isTraced(offset)) + { + Instruction instruction = InstructionFactory.create(codeAttribute.code, + offset); + + instruction.accept(clazz, method, codeAttribute, offset, this); + } + } + + // Apply all accumulated changes to the code. + codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute); + } + + + // Implementations for InstructionVisitor. + + public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) + { + switch (simpleInstruction.opcode) + { + case InstructionConstants.OP_AALOAD: + { + if (isPushingSimpleEnum(offset)) + { + // Load a simple enum integer from an integer array. + replaceInstruction(clazz, + offset, + simpleInstruction, + new SimpleInstruction( + InstructionConstants.OP_IALOAD)); + } + break; + } + case InstructionConstants.OP_AASTORE: + { + if (isPoppingSimpleEnumArray(offset, 2)) + { + // Store a simple enum integer in an integer array. + replaceInstruction(clazz, + offset, + simpleInstruction, + new SimpleInstruction(InstructionConstants.OP_IASTORE)); + + // Replace any producers of null constants. + replaceNullStackEntryProducers(clazz, method, codeAttribute, offset); + } + break; + } + case InstructionConstants.OP_ARETURN: + { + if (isReturningSimpleEnum(clazz, method)) + { + // Return a simple enum integer instead of an enum. + replaceInstruction(clazz, + offset, + simpleInstruction, + new SimpleInstruction(InstructionConstants.OP_IRETURN)); + + // Replace any producers of null constants. + replaceNullStackEntryProducers(clazz, method, codeAttribute, offset); + } + break; + } + } + } + + + public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) + { + int variableIndex = variableInstruction.variableIndex; + + switch (variableInstruction.opcode) + { + case InstructionConstants.OP_ALOAD: + case InstructionConstants.OP_ALOAD_0: + case InstructionConstants.OP_ALOAD_1: + case InstructionConstants.OP_ALOAD_2: + case InstructionConstants.OP_ALOAD_3: + { + if (isPushingSimpleEnum(offset)) + { + // Load a simple enum integer instead of an enum. + replaceInstruction(clazz, + offset, + variableInstruction, + new VariableInstruction(InstructionConstants.OP_ILOAD, + variableIndex)); + + // Replace any producers of null constants. + replaceNullVariableProducers(clazz, + method, + codeAttribute, + offset, + variableIndex); + } + break; + } + case InstructionConstants.OP_ASTORE: + case InstructionConstants.OP_ASTORE_0: + case InstructionConstants.OP_ASTORE_1: + case InstructionConstants.OP_ASTORE_2: + case InstructionConstants.OP_ASTORE_3: + { + if (!partialEvaluator.isSubroutineStart(offset) && + isPoppingSimpleEnum(offset)) + { + // Store a simple enum integer instead of an enum. + replaceInstruction(clazz, + offset, + variableInstruction, + new VariableInstruction(InstructionConstants.OP_ISTORE, + variableIndex)); + + // Replace any producers of null constants. + replaceNullStackEntryProducers(clazz, method, codeAttribute, offset); + } + break; + } + } + } + + + public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) + { + switch (constantInstruction.opcode) + { + case InstructionConstants.OP_PUTSTATIC: + case InstructionConstants.OP_PUTFIELD: + { + // Replace any producers of null constants. + invocationClazz = clazz; + invocationMethod = method; + invocationCodeAttribute = codeAttribute; + invocationOffset = offset; + clazz.constantPoolEntryAccept(constantInstruction.constantIndex, + nullParameterFixer); + break; + } + case InstructionConstants.OP_INVOKEVIRTUAL: + { + // Check if the instruction is calling a simple enum. + String invokedMethodName = + clazz.getRefName(constantInstruction.constantIndex); + String invokedMethodType = + clazz.getRefType(constantInstruction.constantIndex); + int stackEntryIndex = + ClassUtil.internalMethodParameterSize(invokedMethodType); + if (isPoppingSimpleEnum(offset, stackEntryIndex)) + { + replaceSupportedMethod(clazz, + offset, + constantInstruction, + invokedMethodName, + invokedMethodType); + } + + // Fall through to check the parameters. + } + case InstructionConstants.OP_INVOKESPECIAL: + case InstructionConstants.OP_INVOKESTATIC: + case InstructionConstants.OP_INVOKEINTERFACE: + { + // Replace any producers of null constants. + invocationClazz = clazz; + invocationMethod = method; + invocationCodeAttribute = codeAttribute; + invocationOffset = offset; + clazz.constantPoolEntryAccept(constantInstruction.constantIndex, + nullParameterFixer); + break; + } + case InstructionConstants.OP_ANEWARRAY: + { + int constantIndex = constantInstruction.constantIndex; + + if (isReferencingSimpleEnum(clazz, constantIndex) && + !ClassUtil.isInternalArrayType(clazz.getClassName(constantIndex))) + { + // Create an integer array instead of an enum array. + replaceInstruction(clazz, + offset, + constantInstruction, + new SimpleInstruction(InstructionConstants.OP_NEWARRAY, + InstructionConstants.ARRAY_T_INT)); + } + break; + } + case InstructionConstants.OP_CHECKCAST: + { + if (isPoppingSimpleEnum(offset)) + { + // Enum classes can only be simple if the checkcast + // succeeds, so we can delete it. + deleteInstruction(clazz, + offset, + constantInstruction); + + // Replace any producers of null constants. + replaceNullStackEntryProducers(clazz, method, codeAttribute, offset); + } + break; + } + case InstructionConstants.OP_INSTANCEOF: + { + if (isPoppingSimpleEnum(offset)) + { + // Enum classes can only be simple if the instanceof + // succeeds, so we can push a constant result. + replaceInstruction(clazz, + offset, + constantInstruction, + new SimpleInstruction(InstructionConstants.OP_ICONST_1)); + + // Replace any producers of null constants. + replaceNullStackEntryProducers(clazz, method, codeAttribute, offset); + } + break; + } + } + } + + + public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) + { + switch (branchInstruction.opcode) + { + case InstructionConstants.OP_IFACMPEQ: + { + if (isPoppingSimpleEnum(offset)) + { + // Compare simple enum integers instead of enums. + replaceInstruction(clazz, + offset, + branchInstruction, + new BranchInstruction(InstructionConstants.OP_IFICMPEQ, + branchInstruction.branchOffset)); + } + break; + } + case InstructionConstants.OP_IFACMPNE: + { + if (isPoppingSimpleEnum(offset)) + { + // Compare simple enum integers instead of enums. + replaceInstruction(clazz, + offset, + branchInstruction, + new BranchInstruction(InstructionConstants.OP_IFICMPNE, + branchInstruction.branchOffset)); + } + break; + } + case InstructionConstants.OP_IFNULL: + { + if (isPoppingSimpleEnum(offset)) + { + // Compare with 0 instead of null. + replaceInstruction(clazz, + offset, + branchInstruction, + new BranchInstruction( + InstructionConstants.OP_IFEQ, + branchInstruction.branchOffset)); + } + break; + } + case InstructionConstants.OP_IFNONNULL: + { + if (isPoppingSimpleEnum(offset)) + { + // Compare with 0 instead of null. + replaceInstruction(clazz, + offset, + branchInstruction, + new BranchInstruction(InstructionConstants.OP_IFNE, + branchInstruction.branchOffset)); + } + break; + } + } + } + + + public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction) + { + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitStringConstant(Clazz clazz, StringConstant stringConstant) + { + // Does the constant refer to a simple enum type? + isSimpleEnum = isSimpleEnum(stringConstant.referencedClass); + } + + + public void visitClassConstant(Clazz clazz, ClassConstant classConstant) + { + // Does the constant refer to a simple enum type? + isSimpleEnum = isSimpleEnum(classConstant.referencedClass); + } + + + // Implementations for ParameterVisitor. + + public void visitParameter(Clazz clazz, Member member, int parameterIndex, int parameterCount, int parameterOffset, int parameterSize, String parameterType, Clazz referencedClass) + { + // Check if the parameter is passing a simple enum as a more general + // type. + if (!ClassUtil.isInternalPrimitiveType(parameterType.charAt(0)) && + isSimpleEnum(referencedClass)) + { + // Replace any producers of null constants for this parameter. + int stackEntryIndex = parameterSize - parameterOffset - 1; + + replaceNullStackEntryProducers(invocationClazz, + invocationMethod, + invocationCodeAttribute, + invocationOffset, + stackEntryIndex); + } + } + + + // Small utility methods. + + /** + * Returns whether the constant at the given offset is referencing a + * simple enum class. + */ + private boolean isReferencingSimpleEnum(Clazz clazz, int constantIndex) + { + isSimpleEnum = false; + + clazz.constantPoolEntryAccept(constantIndex, this); + + return isSimpleEnum; + } + + + /** + * Returns whether the given method is returning a simple enum class. + */ + private boolean isReturningSimpleEnum(Clazz clazz, Method method) + { + String descriptor = method.getDescriptor(clazz); + String returnType = ClassUtil.internalMethodReturnType(descriptor); + + if (ClassUtil.isInternalClassType(returnType) && + !ClassUtil.isInternalArrayType(returnType)) + { + Clazz[] referencedClasses = + ((ProgramMethod)method).referencedClasses; + + if (referencedClasses != null) + { + int returnedClassIndex = + new DescriptorClassEnumeration(descriptor).classCount() - 1; + + Clazz returnedClass = referencedClasses[returnedClassIndex]; + + return isSimpleEnum(returnedClass); + } + } + + return false; + } + + + /** + * Returns whether the instruction at the given offset is pushing a simple + * enum class. + */ + private boolean isPushingSimpleEnum(int offset) + { + ReferenceValue referenceValue = + partialEvaluator.getStackAfter(offset).getTop(0).referenceValue(); + + Clazz referencedClass = referenceValue.getReferencedClass(); + + return isSimpleEnum(referencedClass) && + !ClassUtil.isInternalArrayType(referenceValue.getType()); + } + + + /** + * Returns whether the instruction at the given offset is popping a simple + * enum class. + */ + private boolean isPoppingSimpleEnum(int offset) + { + return isPoppingSimpleEnum(offset, 0); + } + + + /** + * Returns whether the instruction at the given offset is popping a simple + * enum class. + */ + private boolean isPoppingSimpleEnum(int offset, int stackEntryIndex) + { + ReferenceValue referenceValue = + partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue(); + + return isSimpleEnum(referenceValue.getReferencedClass()) && + !ClassUtil.isInternalArrayType(referenceValue.getType()); + } + + + /** + * Returns whether the instruction at the given offset is popping a simple + * enum type. This includes simple enum arrays. + */ + private boolean isPoppingSimpleEnumType(int offset, int stackEntryIndex) + { + ReferenceValue referenceValue = + partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue(); + + return isSimpleEnum(referenceValue.getReferencedClass()); + } + + + /** + * Returns whether the instruction at the given offset is popping a + * one-dimensional simple enum array. + */ + private boolean isPoppingSimpleEnumArray(int offset, int stackEntryIndex) + { + ReferenceValue referenceValue = + partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue(); + + return isSimpleEnum(referenceValue.getReferencedClass()) && + ClassUtil.internalArrayTypeDimensionCount(referenceValue.getType()) == 1; + } + + + /** + * Returns whether the given class is not null and a simple enum class. + */ + private boolean isSimpleEnum(Clazz clazz) + { + return clazz != null && + SimpleEnumMarker.isSimpleEnum(clazz); + } + + + /** + * Returns whether the specified enum method is supported for simple enums. + */ + private void replaceSupportedMethod(Clazz clazz, + int offset, + Instruction instruction, + String name, + String type) + { + if (name.equals(ClassConstants.METHOD_NAME_ORDINAL) && + type.equals(ClassConstants.METHOD_TYPE_ORDINAL)) + { + Instruction[] replacementInstructions = new Instruction[] + { + new SimpleInstruction(InstructionConstants.OP_ICONST_1), + new SimpleInstruction(InstructionConstants.OP_ISUB), + }; + + replaceInstructions(clazz, + offset, + instruction, + replacementInstructions); + } + } + + + /** + * Replaces the instruction at the given offset by the given instructions. + */ + private void replaceInstructions(Clazz clazz, + int offset, + Instruction instruction, + Instruction[] replacementInstructions) + { + if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstructions.length+" instructions"); + + codeAttributeEditor.replaceInstruction(offset, replacementInstructions); + + // Visit the instruction, if required. + if (extraInstructionVisitor != null) + { + // Note: we're not passing the right arguments for now, knowing that + // they aren't used anyway. + instruction.accept(clazz, null, null, offset, extraInstructionVisitor); + } + } + + + /** + * Replaces the instruction at the given offset by the given instruction, + * popping any now unused stack entries. + */ + private void replaceInstruction(Clazz clazz, + int offset, + Instruction instruction, + Instruction replacementInstruction) + { + // Pop unneeded stack entries if necessary. + int popCount = + instruction.stackPopCount(clazz) - + replacementInstruction.stackPopCount(clazz); + + insertPopInstructions(offset, popCount); + + if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstruction.toString()+(popCount == 0 ? "" : " ("+popCount+" pops)")); + + codeAttributeEditor.replaceInstruction(offset, replacementInstruction); + + // Visit the instruction, if required. + if (extraInstructionVisitor != null) + { + // Note: we're not passing the right arguments for now, knowing that + // they aren't used anyway. + instruction.accept(clazz, null, null, offset, extraInstructionVisitor); + } + } + + + /** + * Deletes the instruction at the given offset, popping any now unused + * stack entries. + */ + private void deleteInstruction(Clazz clazz, + int offset, + Instruction instruction) + { + // Pop unneeded stack entries if necessary. + //int popCount = instruction.stackPopCount(clazz); + // + //insertPopInstructions(offset, popCount); + // + //if (DEBUG) System.out.println(" Deleting instruction "+instruction.toString(offset)+(popCount == 0 ? "" : " ("+popCount+" pops)")); + + if (DEBUG) System.out.println(" Deleting instruction "+instruction.toString(offset)); + + codeAttributeEditor.deleteInstruction(offset); + + // Visit the instruction, if required. + if (extraInstructionVisitor != null) + { + // Note: we're not passing the right arguments for now, knowing that + // they aren't used anyway. + instruction.accept(clazz, null, null, offset, extraInstructionVisitor); + } + } + + + /** + * Pops the given number of stack entries before the instruction at the + * given offset. + */ + private void insertPopInstructions(int offset, int popCount) + { + switch (popCount) + { + case 0: + { + break; + } + case 1: + { + // Insert a single pop instruction. + Instruction popInstruction = + new SimpleInstruction(InstructionConstants.OP_POP); + + codeAttributeEditor.insertBeforeInstruction(offset, + popInstruction); + break; + } + case 2: + { + // Insert a single pop2 instruction. + Instruction popInstruction = + new SimpleInstruction(InstructionConstants.OP_POP2); + + codeAttributeEditor.insertBeforeInstruction(offset, + popInstruction); + break; + } + default: + { + // Insert the specified number of pop instructions. + Instruction[] popInstructions = + new Instruction[popCount / 2 + popCount % 2]; + + Instruction popInstruction = + new SimpleInstruction(InstructionConstants.OP_POP2); + + for (int index = 0; index < popCount / 2; index++) + { + popInstructions[index] = popInstruction; + } + + if (popCount % 2 == 1) + { + popInstruction = + new SimpleInstruction(InstructionConstants.OP_POP); + + popInstructions[popCount / 2] = popInstruction; + } + + codeAttributeEditor.insertBeforeInstruction(offset, + popInstructions); + break; + } + } + } + + + /** + * Replaces aconst_null producers of the consumer of the top stack entry + * at the given offset by iconst_0. + */ + private void replaceNullStackEntryProducers(Clazz clazz, + Method method, + CodeAttribute codeAttribute, + int consumerOffset) + { + replaceNullStackEntryProducers(clazz, method, codeAttribute, consumerOffset, 0); + } + + + /** + * Replaces aconst_null producers of the specified stack entry by + * iconst_0. + */ + private void replaceNullStackEntryProducers(Clazz clazz, + Method method, + CodeAttribute codeAttribute, + int consumerOffset, + int stackEntryIndex) + { + InstructionOffsetValue producerOffsets = + partialEvaluator.getStackBefore(consumerOffset).getTopActualProducerValue(stackEntryIndex).instructionOffsetValue(); + + for (int index = 0; index < producerOffsets.instructionOffsetCount(); index++) + { + int producerOffset = producerOffsets.instructionOffset(index); + + // TODO: A method might be pushing the null constant. + if (producerOffset >= 0 && + codeAttribute.code[producerOffset] == InstructionConstants.OP_ACONST_NULL) + { + // Replace pushing null by pushing 0. + replaceInstruction(clazz, + producerOffset, + new SimpleInstruction(InstructionConstants.OP_ACONST_NULL), + new SimpleInstruction(InstructionConstants.OP_ICONST_0)); + } + } + } + + + /** + * Replaces aconst_null/astore producers of the specified reference variable by + * iconst_0/istore. + */ + private void replaceNullVariableProducers(Clazz clazz, + Method method, + CodeAttribute codeAttribute, + int consumerOffset, + int variableIndex) + { + InstructionOffsetValue producerOffsets = + partialEvaluator.getVariablesBefore(consumerOffset).getProducerValue(variableIndex).instructionOffsetValue(); + + for (int index = 0; index < producerOffsets.instructionOffsetCount(); index++) + { + int producerOffset = producerOffsets.instructionOffset(index); + + if (producerOffset >= 0 && + partialEvaluator.getVariablesAfter(producerOffset).getValue(variableIndex).referenceValue().isNull() == Value.ALWAYS) + { + // Replace loading null by loading 0. + replaceInstruction(clazz, + producerOffset, + new VariableInstruction(InstructionConstants.OP_ASTORE, variableIndex), + new VariableInstruction(InstructionConstants.OP_ISTORE, variableIndex)); + + // Replace pushing null by pushing 0. + replaceNullStackEntryProducers(clazz, method, codeAttribute, producerOffset); + } + } + } +} diff --git a/src/proguard/optimize/evaluation/StoringInvocationUnit.java b/src/proguard/optimize/evaluation/StoringInvocationUnit.java index 846f685..271b654 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.evaluation.value.*; import proguard.optimize.info.*; /** - * This InvocationUbit stores parameter values and return values with the + * This InvocationUnit stores parameter values and return values with the * methods that are invoked. * * @see LoadingInvocationUnit @@ -126,7 +126,7 @@ extends BasicInvocationUnit generalizeMethodReturnValue(method, value); } } - + // Small utility methods. diff --git a/src/proguard/optimize/evaluation/TracedBranchUnit.java b/src/proguard/optimize/evaluation/TracedBranchUnit.java index e6acf6f..9e55275 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 73efddc..bef1445 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,11 +21,11 @@ package proguard.optimize.evaluation; import proguard.classfile.*; +import proguard.classfile.attribute.*; import proguard.classfile.attribute.visitor.*; import proguard.classfile.editor.*; -import proguard.classfile.visitor.MemberVisitor; -import proguard.classfile.attribute.*; import proguard.classfile.util.*; +import proguard.classfile.visitor.MemberVisitor; /** * This AttributeVisitor optimizes variable allocation based on their the liveness, @@ -110,7 +110,7 @@ implements AttributeVisitor, codeAttribute.attributesAccept(clazz, method, this); int startIndex = - (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 || + (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0 || reuseThis ? 0 : 1; int parameterSize = diff --git a/src/proguard/optimize/info/AccessMethodMarker.java b/src/proguard/optimize/info/AccessMethodMarker.java index e4c8d7c..4c3c17b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 @@ package proguard.optimize.info; import proguard.classfile.*; -import proguard.classfile.attribute.*; -import proguard.classfile.attribute.visitor.*; +import proguard.classfile.attribute.CodeAttribute; import proguard.classfile.constant.*; import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.instruction.*; @@ -110,7 +109,7 @@ implements InstructionVisitor, { int accessFlags = clazz.getAccessFlags(); - if ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) == 0) + if ((accessFlags & ClassConstants.ACC_PUBLIC) == 0) { setAccessesPackageCode(invokingMethod); } @@ -123,15 +122,15 @@ implements InstructionVisitor, { int accessFlags = member.getAccessFlags(); - if ((accessFlags & ClassConstants.INTERNAL_ACC_PRIVATE) != 0) + if ((accessFlags & ClassConstants.ACC_PRIVATE) != 0) { setAccessesPrivateCode(invokingMethod); } - else if ((accessFlags & ClassConstants.INTERNAL_ACC_PROTECTED) != 0) + else if ((accessFlags & ClassConstants.ACC_PROTECTED) != 0) { setAccessesProtectedCode(invokingMethod); } - else if ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) == 0) + else if ((accessFlags & ClassConstants.ACC_PUBLIC) == 0) { setAccessesPackageCode(invokingMethod); } diff --git a/src/proguard/optimize/info/BackwardBranchMarker.java b/src/proguard/optimize/info/BackwardBranchMarker.java index 07bfefb..089b66e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 8f87a08..2894d2a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 762e7de..0c32151 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 1752f0c..31ee1a8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ package proguard.optimize.info; import proguard.classfile.*; -import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.ClassVisitor; /** diff --git a/src/proguard/optimize/info/ClassOptimizationInfo.java b/src/proguard/optimize/info/ClassOptimizationInfo.java index dbe041e..5ac56f9 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 isSimpleEnum = false; private boolean containsStaticInitializer = false; private boolean containsPackageVisibleMembers = false; private boolean invokesPackageVisibleMembers = false; @@ -88,6 +89,18 @@ public class ClassOptimizationInfo } + public void setSimpleEnum(boolean simple) + { + isSimpleEnum = simple; + } + + + public boolean isSimpleEnum() + { + return isSimpleEnum; + } + + public void setContainsStaticInitializer() { containsStaticInitializer = true; @@ -157,7 +170,6 @@ public class ClassOptimizationInfo public static ClassOptimizationInfo getClassOptimizationInfo(Clazz clazz) { Object visitorInfo = clazz.getVisitorInfo(); - return visitorInfo instanceof ClassOptimizationInfo ? (ClassOptimizationInfo)visitorInfo : null; diff --git a/src/proguard/optimize/info/ClassOptimizationInfoSetter.java b/src/proguard/optimize/info/ClassOptimizationInfoSetter.java index f3d78e2..b9211e7 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.optimize.info; -import proguard.classfile.*; +import proguard.classfile.ProgramClass; import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.ClassVisitor; import proguard.optimize.KeepMarker; diff --git a/src/proguard/optimize/info/DotClassFilter.java b/src/proguard/optimize/info/DotClassFilter.java index c3fd878..8ab4f98 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 ef5cfd1..d9519ac 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/DynamicInvocationMarker.java b/src/proguard/optimize/info/DynamicInvocationMarker.java new file mode 100644 index 0000000..daee6b4 --- /dev/null +++ b/src/proguard/optimize/info/DynamicInvocationMarker.java @@ -0,0 +1,79 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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.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.classfile.visitor.*; + +/** + * This InstructionVisitor marks whether the methods whose instructions it + * visits contain the invokedynamic instruction. + * + * @author Eric Lafortune + */ +public class DynamicInvocationMarker +extends SimplifiedVisitor +implements InstructionVisitor, + ConstantVisitor, + ClassVisitor, + MemberVisitor +{ + // 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) + { + if (constantInstruction.opcode == InstructionConstants.OP_INVOKEDYNAMIC) + { + setInvokesDynamically(method); + } + } + + + // Small utility methods. + + private static void setInvokesDynamically(Method method) + { + MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method); + if (info != null) + { + info.setInvokesDynamically(); + } + } + + + /** + * Returns whether the given method calls the invokedynamic instruction. + */ + public static boolean invokesDynamically(Method method) + { + MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method); + return info == null || info.invokesDynamically(); + } +} diff --git a/src/proguard/optimize/info/ExceptionInstructionChecker.java b/src/proguard/optimize/info/ExceptionInstructionChecker.java index 4bfa96f..a32a1d3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,12 +22,9 @@ package proguard.optimize.info; import proguard.classfile.*; import proguard.classfile.attribute.CodeAttribute; -import proguard.classfile.constant.RefConstant; -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.MemberVisitor; /** * This class can tell whether an instruction might throw exceptions. @@ -45,15 +42,90 @@ implements InstructionVisitor /** - * Returns whether the given instruction may throw exceptions. + * Returns whether the specified method may throw exceptions. */ - public boolean mayThrowExceptions(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) + public boolean mayThrowExceptions(Clazz clazz, + Method method, + CodeAttribute codeAttribute) { - mayThrowExceptions = false; + return mayThrowExceptions(clazz, + method, + codeAttribute, + 0, + codeAttribute.u4codeLength); + } + + + /** + * Returns whether the specified block of code may throw exceptions. + */ + public boolean mayThrowExceptions(Clazz clazz, + Method method, + CodeAttribute codeAttribute, + int startOffset, + int endOffset) + { + byte[] code = codeAttribute.code; + + // Go over all instructions. + int offset = startOffset; + while (offset < endOffset) + { + // Get the current instruction. + Instruction instruction = InstructionFactory.create(code, offset); - instruction.accept(clazz, method, codeAttribute, offset, this); + // Check if it may be throwing exceptions. + if (mayThrowExceptions(clazz, + method, + codeAttribute, + offset, + instruction)) + { + return true; + } - return mayThrowExceptions; + // Go to the next instruction. + offset += instruction.length(offset); + } + + return false; + } + + + /** + * Returns whether the specified instruction may throw exceptions. + */ + public boolean mayThrowExceptions(Clazz clazz, + Method method, + CodeAttribute codeAttribute, + int offset) + { + Instruction instruction = InstructionFactory.create(codeAttribute.code, offset); + + return mayThrowExceptions(clazz, + method, + codeAttribute, + offset, + instruction); + } + + + /** + * Returns whether the given instruction may throw exceptions. + */ + public boolean mayThrowExceptions(Clazz clazz, + Method method, + CodeAttribute codeAttribute, + int offset, + Instruction instruction) + { + return instruction.mayThrowExceptions(); + +// mayThrowExceptions = false; +// +// instruction.accept(clazz, method, codeAttribute, offset, this); +// +// return mayThrowExceptions; } @@ -64,15 +136,13 @@ implements InstructionVisitor public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) { - byte opcode = simpleInstruction.opcode; - // Check for instructions that may throw exceptions. // 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) + switch (simpleInstruction.opcode) { case InstructionConstants.OP_IDIV: case InstructionConstants.OP_LDIV: @@ -101,16 +171,13 @@ implements InstructionVisitor // These instructions may throw exceptions. mayThrowExceptions = true; } - } public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) { - byte opcode = constantInstruction.opcode; - // Check for instructions that may throw exceptions. - switch (opcode) + switch (constantInstruction.opcode) { case InstructionConstants.OP_GETSTATIC: case InstructionConstants.OP_PUTSTATIC: @@ -128,7 +195,6 @@ implements InstructionVisitor case InstructionConstants.OP_MULTIANEWARRAY: // These instructions may throw exceptions. mayThrowExceptions = true; - } // case InstructionConstants.OP_INVOKEVIRTUAL: // case InstructionConstants.OP_INVOKESPECIAL: @@ -136,6 +202,7 @@ implements InstructionVisitor // 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 0fa9167..730eead 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,11 +21,11 @@ package proguard.optimize.info; import proguard.classfile.*; -import proguard.classfile.attribute.visitor.*; import proguard.classfile.attribute.*; -import proguard.classfile.util.*; -import proguard.evaluation.value.*; +import proguard.classfile.attribute.visitor.*; +import proguard.classfile.util.SimplifiedVisitor; import proguard.evaluation.ConstantValueFactory; +import proguard.evaluation.value.*; /** * This class stores some optimization information that can be attached to @@ -37,8 +37,9 @@ public class FieldOptimizationInfo extends SimplifiedVisitor implements AttributeVisitor { - private static final SpecificValueFactory VALUE_FACTORY = new SpecificValueFactory(); - private static final ConstantValueFactory CONSTANT_VALUE_FACTORY = new ConstantValueFactory(VALUE_FACTORY); + private static final ParticularValueFactory VALUE_FACTORY = new ParticularValueFactory(); + private static final ConstantValueFactory CONSTANT_VALUE_FACTORY = new ConstantValueFactory(VALUE_FACTORY); + private static final InitialValueFactory INITIAL_VALUE_FACTORY = new InitialValueFactory(VALUE_FACTORY); private boolean isWritten; private boolean isRead; @@ -52,20 +53,9 @@ implements AttributeVisitor int accessFlags = field.getAccessFlags(); isWritten = - isRead = (accessFlags & ClassConstants.INTERNAL_ACC_VOLATILE) != 0; + isRead = (accessFlags & ClassConstants.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)); - } + resetValue(clazz, field); } @@ -129,6 +119,30 @@ implements AttributeVisitor } + public void resetValue(Clazz clazz, Field field) + { + int accessFlags = field.getAccessFlags(); + + value = null; + + // See if we can initialize a static field with a constant value. + if ((accessFlags & ClassConstants.ACC_STATIC) != 0) + { + field.accept(clazz, new AllAttributeVisitor(this)); + } + + // Otherwise initialize a non-final field with the default value. + // Conservatively, even a final field needs to be initialized with the + // default value, because it may be accessed before it is set. + if (value == null && + (SideEffectInstructionChecker.OPTIMIZE_CONSERVATIVELY || + (accessFlags & ClassConstants.ACC_FINAL) == 0)) + { + value = INITIAL_VALUE_FACTORY.createValue(field.getDescriptor(clazz)); + } + } + + public void generalizeValue(Value value) { this.value = this.value != null ? @@ -157,36 +171,6 @@ implements AttributeVisitor // Small utility methods. - private Value initialValue(String type) - { - switch (type.charAt(0)) - { - case ClassConstants.INTERNAL_TYPE_BOOLEAN: - case ClassConstants.INTERNAL_TYPE_BYTE: - case ClassConstants.INTERNAL_TYPE_CHAR: - case ClassConstants.INTERNAL_TYPE_SHORT: - case ClassConstants.INTERNAL_TYPE_INT: - return VALUE_FACTORY.createIntegerValue(0); - - case ClassConstants.INTERNAL_TYPE_LONG: - return VALUE_FACTORY.createLongValue(0L); - - case ClassConstants.INTERNAL_TYPE_FLOAT: - return VALUE_FACTORY.createFloatValue(0.0f); - - case ClassConstants.INTERNAL_TYPE_DOUBLE: - return VALUE_FACTORY.createDoubleValue(0.0); - - case ClassConstants.INTERNAL_TYPE_CLASS_START: - case ClassConstants.INTERNAL_TYPE_ARRAY: - return VALUE_FACTORY.createReferenceValueNull(); - - default: - throw new IllegalArgumentException("Invalid type ["+type+"]"); - } - } - - public static void setFieldOptimizationInfo(Clazz clazz, Field field) { field.setVisitorInfo(new FieldOptimizationInfo(clazz, field)); diff --git a/src/proguard/optimize/info/InstanceofClassFilter.java b/src/proguard/optimize/info/InstanceofClassFilter.java index 7cd85bc..ab345fb 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 96d5baf..3556dd8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 a659f06..7822205 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 b4afffd..3f90991 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 3c27c93..ad64cf9 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/optimize/info/MethodInvocationMarker.java b/src/proguard/optimize/info/MethodInvocationMarker.java index afb2336..c9a9131 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 fe754e5..9bfdb50 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 +38,7 @@ public class MethodOptimizationInfo private boolean catchesExceptions = false; private boolean branchesBackward = false; private boolean invokesSuperMethods = false; + private boolean invokesDynamically = false; private boolean accessesPrivateCode = false; private boolean accessesPackageCode = false; private boolean accessesProtectedCode = false; @@ -58,7 +59,7 @@ public class MethodOptimizationInfo int parameterCount = ClassUtil.internalMethodParameterCount(method.getDescriptor(clazz)); - if ((method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) == 0) + if ((method.getAccessFlags() & ClassConstants.ACC_STATIC) == 0) { parameterCount++; } @@ -142,6 +143,18 @@ public class MethodOptimizationInfo } + public void setInvokesDynamically() + { + invokesDynamically = true; + } + + + public boolean invokesDynamically() + { + return invokesDynamically; + } + + public void setAccessesPrivateCode() { accessesPrivateCode = true; @@ -256,6 +269,13 @@ public class MethodOptimizationInfo } + // For setting enum return values. + public void setReturnValue(Value returnValue) + { + this.returnValue = returnValue; + } + + public void merge(MethodOptimizationInfo other) { if (other != null) @@ -266,6 +286,7 @@ public class MethodOptimizationInfo this.catchesExceptions |= other.catchesExceptions; this.branchesBackward |= other.branchesBackward; this.invokesSuperMethods |= other.invokesSuperMethods; + this.invokesDynamically |= other.invokesDynamically; this.accessesPrivateCode |= other.accessesPrivateCode; this.accessesPackageCode |= other.accessesPackageCode; this.accessesProtectedCode |= other.accessesProtectedCode; diff --git a/src/proguard/optimize/info/NoSideEffectMethodMarker.java b/src/proguard/optimize/info/NoSideEffectMethodMarker.java index bf5ce45..34549b3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/optimize/info/NonPrivateMemberMarker.java b/src/proguard/optimize/info/NonPrivateMemberMarker.java index 06f8500..152e114 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -49,13 +49,13 @@ implements ClassVisitor, programClass.constantPoolEntriesAccept(this); // Explicitly mark the <clinit> method. - programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT, - ClassConstants.INTERNAL_METHOD_TYPE_CLINIT, + programClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT, + ClassConstants.METHOD_TYPE_CLINIT, this); // Explicitly mark the parameterless <init> method. - programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_INIT, - ClassConstants.INTERNAL_METHOD_TYPE_INIT, + programClass.methodAccept(ClassConstants.METHOD_NAME_INIT, + ClassConstants.METHOD_TYPE_INIT, this); // Mark all methods that may have implementations. diff --git a/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java index 02e1a18..7f1dfdb 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 ClassVisitor, public void visitAnyClass(Clazz clazz) { // Check the class itself. - if ((clazz.getAccessFlags() & ClassConstants.INTERNAL_ACC_PUBLIC) == 0) + if ((clazz.getAccessFlags() & ClassConstants.ACC_PUBLIC) == 0) { setPackageVisibleMembers(clazz); } @@ -57,8 +57,8 @@ implements ClassVisitor, public void visitAnyMember(Clazz clazz, Member member) { if ((member.getAccessFlags() & - (ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_PUBLIC)) == 0) + (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_PUBLIC)) == 0) { setPackageVisibleMembers(clazz); } diff --git a/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java index 3148e3d..6a8e329 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 @@ package proguard.optimize.info; import proguard.classfile.*; -import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.constant.*; +import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.*; @@ -89,7 +89,7 @@ implements ConstantVisitor, public void visitAnyClass(Clazz clazz) { if ((clazz.getAccessFlags() & - ClassConstants.INTERNAL_ACC_PUBLIC) == 0) + ClassConstants.ACC_PUBLIC) == 0) { setInvokesPackageVisibleMembers(referencingClass); } @@ -101,8 +101,8 @@ implements ConstantVisitor, public void visitAnyMember(Clazz clazz, Member member) { if ((member.getAccessFlags() & - (ClassConstants.INTERNAL_ACC_PUBLIC | - ClassConstants.INTERNAL_ACC_PRIVATE)) == 0) + (ClassConstants.ACC_PUBLIC | + ClassConstants.ACC_PRIVATE)) == 0) { setInvokesPackageVisibleMembers(referencingClass); } diff --git a/src/proguard/optimize/info/ParameterUsageMarker.java b/src/proguard/optimize/info/ParameterUsageMarker.java index a2a264d..0061148 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -89,7 +89,7 @@ implements MemberVisitor, // Must we mark the 'this' parameter? if (markThisParameter && - (accessFlags & ClassConstants.INTERNAL_ACC_STATIC) == 0) + (accessFlags & ClassConstants.ACC_STATIC) == 0) { // Mark the 'this' parameter. markParameterUsed(programMethod, 0); @@ -100,19 +100,19 @@ implements MemberVisitor, { // Mark all parameters, without the 'this' parameter. markUsedParameters(programMethod, - (accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? + (accessFlags & ClassConstants.ACC_STATIC) != 0 ? -1L : -2L); } // Is it a native method? - if ((accessFlags & ClassConstants.INTERNAL_ACC_NATIVE) != 0) + if ((accessFlags & ClassConstants.ACC_NATIVE) != 0) { // Mark all parameters. markUsedParameters(programMethod, -1L); } // Is it an abstract method? - else if ((accessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0) + else if ((accessFlags & ClassConstants.ACC_ABSTRACT) != 0) { // Mark the 'this' parameter. markParameterUsed(programMethod, 0); @@ -123,10 +123,10 @@ implements MemberVisitor, { // Is the method not static, but synchronized, or can it have // other implementations, or is it a class instance initializer? - if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) == 0 && - ((accessFlags & ClassConstants.INTERNAL_ACC_SYNCHRONIZED) != 0 || + if ((accessFlags & ClassConstants.ACC_STATIC) == 0 && + ((accessFlags & ClassConstants.ACC_SYNCHRONIZED) != 0 || programClass.mayHaveImplementations(programMethod) || - programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))) + programMethod.getName(programClass).equals(ClassConstants.METHOD_NAME_INIT))) { // Mark the 'this' parameter. markParameterUsed(programMethod, 0); diff --git a/src/proguard/optimize/info/ReadWriteFieldMarker.java b/src/proguard/optimize/info/ReadWriteFieldMarker.java index 6bd4b2f..ea98d3e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 91f1f02..49a1281 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 @@ import java.util.*; /** * This class can tell whether an instruction has any side effects outside of - * its method. Return instructions can be included or not. + * its method. Return instructions and local field accesses can be included or + * not. * * @see ReadWriteFieldMarker * @see StaticInitializerContainingClassMarker @@ -47,17 +48,25 @@ implements InstructionVisitor, ConstantVisitor, MemberVisitor { - private static final boolean OPTIMIZE_CONSERVATIVELY = System.getProperty("optimize.conservatively") != null; + 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 boolean writingField; private Clazz referencingClass; private boolean hasSideEffects; + /** + * Creates a new SideEffectInstructionChecker + * @param includeReturnInstructions specifies whether return instructions + * count as side effects. + * @param includeLocalFieldAccess specifies whether reading or writing + * local fields counts as side effects. + */ public SideEffectInstructionChecker(boolean includeReturnInstructions, boolean includeLocalFieldAccess) { @@ -96,6 +105,10 @@ implements InstructionVisitor, // Check for instructions that might cause side effects. switch (opcode) { + 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: @@ -104,8 +117,13 @@ implements InstructionVisitor, case InstructionConstants.OP_BALOAD: case InstructionConstants.OP_CALOAD: case InstructionConstants.OP_SALOAD: + case InstructionConstants.OP_NEWARRAY: + case InstructionConstants.OP_ARRAYLENGTH: + case InstructionConstants.OP_ANEWARRAY: + case InstructionConstants.OP_MULTIANEWARRAY: // These instructions strictly taken may cause a side effect - // (NullPointerException, ArrayIndexOutOfBoundsException). + // (ArithmeticException, NullPointerException, + // ArrayIndexOutOfBoundsException, NegativeArraySizeException). hasSideEffects = OPTIMIZE_CONSERVATIVELY; break; @@ -160,16 +178,53 @@ implements InstructionVisitor, switch (opcode) { case InstructionConstants.OP_GETSTATIC: + // Check if accessing the field might cause any side effects. + writingField = false; + clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); + break; + 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. + // Check if accessing the field might cause any side effects. + writingField = true; clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); break; case InstructionConstants.OP_GETFIELD: + 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. + writingField = false; + clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); + } + break; + case InstructionConstants.OP_PUTFIELD: + 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. + writingField = true; + clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); + } + break; + + case InstructionConstants.OP_INVOKESPECIAL: + case InstructionConstants.OP_INVOKESTATIC: + // Check if the invoked method is causing any side effects. + clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); + break; + case InstructionConstants.OP_INVOKEVIRTUAL: case InstructionConstants.OP_INVOKEINTERFACE: case InstructionConstants.OP_INVOKEDYNAMIC: @@ -181,15 +236,16 @@ implements InstructionVisitor, } else { - // Check if the field is write-only or volatile, or if the - // invoked method is causing any side effects. + // Check if the invoked method is causing any side effects. clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); } break; + case InstructionConstants.OP_ANEWARRAY: case InstructionConstants.OP_CHECKCAST: + case InstructionConstants.OP_MULTIANEWARRAY: // This instructions strictly taken may cause a side effect - // (ClassCastException). + // (ClassCastException, NegativeArraySizeException). hasSideEffects = OPTIMIZE_CONSERVATIVELY; break; } @@ -252,11 +308,9 @@ implements InstructionVisitor, { 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)))); + ((writingField && ReadWriteFieldMarker.isRead(programField)) || + (programField.getAccessFlags() & ClassConstants.ACC_VOLATILE) != 0 || + mayHaveSideEffects(referencingClass, programClass)); } @@ -267,8 +321,7 @@ implements InstructionVisitor, hasSideEffects = !NoSideEffectMethodMarker.hasNoSideEffects(programMethod) && (SideEffectMethodMarker.hasSideEffects(programMethod) || - (!programClass.equals(referencingClass) && - !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(programClass)))); + mayHaveSideEffects(referencingClass, programClass)); } @@ -285,6 +338,21 @@ implements InstructionVisitor, } + // Small utility methods. + + /** + * Returns whether a field reference or method invocation from the + * referencing class to the referenced class might have any side + * effects. + */ + private boolean mayHaveSideEffects(Clazz referencingClass, Clazz referencedClass) + { + return + !referencedClass.equals(referencingClass) && + !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(referencedClass)); + } + + /** * Returns the set of superclasses and interfaces that are initialized. */ @@ -296,8 +364,8 @@ implements InstructionVisitor, // static initializers. clazz.hierarchyAccept(true, true, true, false, new StaticInitializerContainingClassFilter( - new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_CLINIT, - ClassConstants.INTERNAL_METHOD_TYPE_CLINIT, + new NamedMethodVisitor(ClassConstants.METHOD_NAME_CLINIT, + ClassConstants.METHOD_TYPE_CLINIT, new SideEffectMethodFilter( new MemberToClassVisitor( new ClassCollector(set)))))); diff --git a/src/proguard/optimize/info/SideEffectMethodFilter.java b/src/proguard/optimize/info/SideEffectMethodFilter.java index 52e072a..3821870 100644 --- a/src/proguard/optimize/info/SideEffectMethodFilter.java +++ b/src/proguard/optimize/info/SideEffectMethodFilter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/optimize/info/SideEffectMethodMarker.java b/src/proguard/optimize/info/SideEffectMethodMarker.java index f7953c0..79584e1 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +86,8 @@ implements ClassPoolVisitor, // Initialize the return value. hasSideEffects = (programMethod.getAccessFlags() & - (ClassConstants.INTERNAL_ACC_NATIVE | - ClassConstants.INTERNAL_ACC_SYNCHRONIZED)) != 0; + (ClassConstants.ACC_NATIVE | + ClassConstants.ACC_SYNCHRONIZED)) != 0; // Look further if the method hasn't been marked yet. if (!hasSideEffects) @@ -132,7 +132,7 @@ implements ClassPoolVisitor, int length = codeAttribute.u4codeLength; SideEffectInstructionChecker checker = - method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) ? + method.getName(clazz).equals(ClassConstants.METHOD_NAME_CLINIT) ? initializerSideEffectInstructionChecker : sideEffectInstructionChecker; diff --git a/src/proguard/optimize/info/SimpleEnumFilter.java b/src/proguard/optimize/info/SimpleEnumFilter.java new file mode 100644 index 0000000..8db58f4 --- /dev/null +++ b/src/proguard/optimize/info/SimpleEnumFilter.java @@ -0,0 +1,63 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 simple enums. + * + * @see SimpleEnumMarker + * @author Eric Lafortune + */ +public class SimpleEnumFilter +implements ClassVisitor +{ + private final ClassVisitor classVisitor; + + + public SimpleEnumFilter(ClassVisitor classVisitor) + { + this.classVisitor = classVisitor; + } + + + // Implementations for ClassVisitor. + + public void visitProgramClass(ProgramClass programClass) + { + if (SimpleEnumMarker.isSimpleEnum(programClass)) + { + classVisitor.visitProgramClass(programClass); + } + } + + + public void visitLibraryClass(LibraryClass libraryClass) + { + if (SimpleEnumMarker.isSimpleEnum(libraryClass)) + { + classVisitor.visitLibraryClass(libraryClass); + } + } +}
\ No newline at end of file diff --git a/src/proguard/optimize/info/SimpleEnumMarker.java b/src/proguard/optimize/info/SimpleEnumMarker.java new file mode 100644 index 0000000..dfb1ccb --- /dev/null +++ b/src/proguard/optimize/info/SimpleEnumMarker.java @@ -0,0 +1,75 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is 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 marks all program classes that it visits with a given + * flag for simple enums. + * + * @author Eric Lafortune + */ +public class SimpleEnumMarker +implements ClassVisitor +{ + private final boolean simple; + + + /** + * Creates a new SimpleEnumMarker that marks visited classes with the + * given flag. + */ + public SimpleEnumMarker(boolean simple) + { + this.simple = simple; + } + + + // Implementations for ClassVisitor. + + public void visitLibraryClass(LibraryClass libraryClass) {} + + public void visitProgramClass(ProgramClass programClass) + { + setSimpleEnum(programClass); + } + + + // Small utility methods. + + private void setSimpleEnum(Clazz clazz) + { + ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz); + if (info != null) + { + info.setSimpleEnum(simple); + } + } + + + public static boolean isSimpleEnum(Clazz clazz) + { + ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz); + return info != null && info.isSimpleEnum(); + } +}
\ No newline at end of file diff --git a/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java b/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java index 36aa392..ccb3d31 100644 --- a/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java +++ b/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/StaticInitializerContainingClassMarker.java b/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java index 3a7e642..12e0079 100644 --- a/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java +++ b/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.optimize.info; import proguard.classfile.*; import proguard.classfile.util.SimplifiedVisitor; -import proguard.classfile.visitor.*; +import proguard.classfile.visitor.ClassVisitor; /** * This ClassVisitor marks all classes that contain static initializers. @@ -37,8 +37,8 @@ implements ClassVisitor public void visitAnyClass(Clazz clazz) { - if (clazz.findMethod(ClassConstants.INTERNAL_METHOD_NAME_CLINIT, - ClassConstants.INTERNAL_METHOD_TYPE_CLINIT) != null) + if (clazz.findMethod(ClassConstants.METHOD_NAME_CLINIT, + ClassConstants.METHOD_TYPE_CLINIT) != null) { setStaticInitializer(clazz); } diff --git a/src/proguard/optimize/info/SuperInvocationMarker.java b/src/proguard/optimize/info/SuperInvocationMarker.java index 37b118a..990a9ea 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +69,7 @@ implements InstructionVisitor, { invokesSuperMethods = !clazz.equals(refConstant.referencedClass) && - !refConstant.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT); + !refConstant.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT); } diff --git a/src/proguard/optimize/info/VariableUsageMarker.java b/src/proguard/optimize/info/VariableUsageMarker.java index b189ca9..1d3c04a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/optimize/peephole/BranchTargetFinder.java b/src/proguard/optimize/peephole/BranchTargetFinder.java index 79499f1..507c1f8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +50,14 @@ implements AttributeVisitor, 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 NONE = -1; + // We'll explicitly mark instructions that are not part of a subroutine, + // with NO_SUBROUTINE. Subroutines may just branch back into normal code + // (e.g. due to a break instruction in Java code), and we want to avoid + // marking such normal code as subroutine. The first mark wins, so we're + // assuming that such code is marked as normal code before it is marked + // as subroutine. public static final int UNKNOWN = -1; public static final int NO_SUBROUTINE = -2; @@ -355,24 +360,17 @@ implements AttributeVisitor, currentSubroutineStart = NO_SUBROUTINE; 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; - } - // 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); } while (repeat); // The end of the code is a branch target sentinel. instructionMarks[codeLength] = BRANCH_TARGET; - // Mark branch targets in the exception table. - codeAttribute.exceptionsAccept(clazz, method, this); - if (containsSubroutines) { // Set the subroutine returning flag and the subroutine end at each @@ -487,33 +485,39 @@ implements AttributeVisitor, // Check if this is an instruction of a subroutine. checkSubroutine(offset); - // Check if the instruction is a 'new' instruction. - if (constantInstruction.opcode == InstructionConstants.OP_NEW) + byte opcode = constantInstruction.opcode; + if (opcode == InstructionConstants.OP_NEW) { // Push the 'new' instruction offset on the stack. recentCreationOffsets[recentCreationOffsetIndex++] = offset; } - else + else if (opcode == InstructionConstants.OP_INVOKESPECIAL) { - // Check if the instruction is an initializer invocation. + // Is it calling an instance initializer? isInitializer = false; clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); if (isInitializer) { - // Pop the 'new' instruction offset from the stack. - int recentCreationOffset = recentCreationOffsets[--recentCreationOffsetIndex]; + // Do we have any 'new' instruction offsets on the stack? + if (recentCreationOffsetIndex > 0) + { + // Pop the 'new' instruction offset from the stack. + int recentCreationOffset = recentCreationOffsets[--recentCreationOffsetIndex]; - // Fill it out in the creation offsets. - creationOffsets[offset] = recentCreationOffset; + // Link the creation offset and the initialization offset. + // TODO: There could be multiple initialization offsets. + creationOffsets[offset] = recentCreationOffset; - // Fill out the initialization offsets. - if (recentCreationOffset == AT_METHOD_ENTRY) - { - superInitializationOffset = offset; + initializationOffsets[recentCreationOffset] = offset; } else { - initializationOffsets[recentCreationOffset] = offset; + // Remember the super initialization offset. + // TODO: There could be multiple initialization offsets. + // For instance, in the constructor of the generated class + // groovy.inspect.swingui.GeneratedBytecodeAwareGroovyClassLoader + // in groovy-all-2.2.1.jar. + superInitializationOffset = offset; } } } @@ -613,7 +617,8 @@ implements AttributeVisitor, public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) { - isInitializer = methodrefConstant.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT); + // Remember whether the method is an initializer. + isInitializer = methodrefConstant.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT); } @@ -621,10 +626,24 @@ implements AttributeVisitor, public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) { + int startPC = exceptionInfo.u2startPC; + int endPC = exceptionInfo.u2endPC; + int handlerPC = exceptionInfo.u2handlerPC; + // Mark the exception offsets. - instructionMarks[exceptionInfo.u2startPC] |= EXCEPTION_START; - instructionMarks[exceptionInfo.u2endPC] |= EXCEPTION_END; - instructionMarks[exceptionInfo.u2handlerPC] |= EXCEPTION_HANDLER; + instructionMarks[startPC] |= EXCEPTION_START; + instructionMarks[endPC] |= EXCEPTION_END; + instructionMarks[handlerPC] |= EXCEPTION_HANDLER; + + // Mark the handler as part of a subroutine if necessary. + if (subroutineStarts[handlerPC] == UNKNOWN && + subroutineStarts[startPC] != UNKNOWN) + { + subroutineStarts[handlerPC] = subroutineStarts[startPC]; + + // We'll have to go over all instructions again. + repeat = true; + } } @@ -737,12 +756,6 @@ implements AttributeVisitor, { // 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 378f972..1529c2c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 @@ package proguard.optimize.peephole; import proguard.classfile.*; -import proguard.classfile.util.*; -import proguard.classfile.visitor.*; +import proguard.classfile.util.SimplifiedVisitor; +import proguard.classfile.visitor.ClassVisitor; import proguard.optimize.KeepMarker; /** @@ -66,13 +66,13 @@ implements ClassVisitor // and it is not being kept, // and it doesn't have any subclasses, // then make it final. - if ((programClass.u2accessFlags & (ClassConstants.INTERNAL_ACC_FINAL | - ClassConstants.INTERNAL_ACC_INTERFACE | - ClassConstants.INTERNAL_ACC_ABSTRACT)) == 0 && + if ((programClass.u2accessFlags & (ClassConstants.ACC_FINAL | + ClassConstants.ACC_INTERFACE | + ClassConstants.ACC_ABSTRACT)) == 0 && !KeepMarker.isKept(programClass) && programClass.subClasses == null) { - programClass.u2accessFlags |= ClassConstants.INTERNAL_ACC_FINAL; + programClass.u2accessFlags |= ClassConstants.ACC_FINAL; // Visit the class, if required. if (extraClassVisitor != null) diff --git a/src/proguard/optimize/peephole/ClassMerger.java b/src/proguard/optimize/peephole/ClassMerger.java index aa40c75..9bcc993 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -49,9 +49,11 @@ implements ClassVisitor, ConstantVisitor { //* - private static final boolean DEBUG = false; + private static final boolean DEBUG = false; + private static final boolean DETAILS = false; /*/ - private static boolean DEBUG = System.getProperty("cm") != null; + private static boolean DEBUG = System.getProperty("cm") != null; + private static boolean DETAILS = System.getProperty("cmd") != null; //*/ @@ -152,7 +154,9 @@ implements ClassVisitor, // Don't merge annotation classes, with all their introspection and // infinite recursion. - (programClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_ANNOTATTION) == 0 && + (programClass.getAccessFlags() & ClassConstants.ACC_ANNOTATTION) == 0 && + + (!DETAILS || print(programClass, "Package visibility?")) && // Only merge classes if we can change the access permissions, or // if they are in the same package, or @@ -161,77 +165,117 @@ implements ClassVisitor, (allowAccessModification || ((programClass.getAccessFlags() & targetClass.getAccessFlags() & - ClassConstants.INTERNAL_ACC_PUBLIC) != 0 && + ClassConstants.ACC_PUBLIC) != 0 && !PackageVisibleMemberContainingClassMarker.containsPackageVisibleMembers(programClass) && !PackageVisibleMemberInvokingClassMarker.invokesPackageVisibleMembers(programClass)) || ClassUtil.internalPackageName(programClass.getName()).equals( ClassUtil.internalPackageName(targetClass.getName()))) && + (!DETAILS || print(programClass, "Interface/abstract/single?")) && + // Only merge two classes or two interfaces or two abstract classes, - // or a class into an interface with a single implementation. + // or a single implementation into its interface. ((programClass.getAccessFlags() & - (ClassConstants.INTERNAL_ACC_INTERFACE | - ClassConstants.INTERNAL_ACC_ABSTRACT)) == + (ClassConstants.ACC_INTERFACE | + ClassConstants.ACC_ABSTRACT)) == (targetClass.getAccessFlags() & - (ClassConstants.INTERNAL_ACC_INTERFACE | - ClassConstants.INTERNAL_ACC_ABSTRACT)) || + (ClassConstants.ACC_INTERFACE | + ClassConstants.ACC_ABSTRACT)) || (isOnlySubClass(programClass, targetClass) && + programClass.getSuperClass() != null && (programClass.getSuperClass().equals(targetClass) || programClass.getSuperClass().equals(targetClass.getSuperClass())))) && + (!DETAILS || print(programClass, "Indirect implementation?")) && + // One class must not implement the other class indirectly. !indirectlyImplementedInterfaces(programClass).contains(targetClass) && !targetClass.extendsOrImplements(programClass) && + (!DETAILS || print(programClass, "Interfaces same subinterfaces?")) && + + // Interfaces must have exactly the same subinterfaces, not + // counting themselves, to avoid any loops in the interface + // hierarchy. + ((programClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) == 0 || + (targetClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) == 0 || + subInterfaces(programClass, targetClass).equals(subInterfaces(targetClass, programClass))) && + + (!DETAILS || print(programClass, "Same initialized superclasses?")) && + // The two classes must have the same superclasses and interfaces // with static initializers. initializedSuperClasses(programClass).equals(initializedSuperClasses(targetClass)) && + (!DETAILS || print(programClass, "Same instanceofed superclasses?")) && + // The two classes must have the same superclasses and interfaces // that are tested with 'instanceof'. instanceofedSuperClasses(programClass).equals(instanceofedSuperClasses(targetClass)) && + (!DETAILS || print(programClass, "Same caught superclasses?")) && + // The two classes must have the same superclasses that are caught // as exceptions. caughtSuperClasses(programClass).equals(caughtSuperClasses(targetClass)) && + (!DETAILS || print(programClass, "Not .classed?")) && + // The two classes must not both be part of a .class construct. !(DotClassMarker.isDotClassed(programClass) && DotClassMarker.isDotClassed(targetClass)) && + (!DETAILS || print(programClass, "No clashing fields?")) && + // The classes must not have clashing fields. !haveAnyIdenticalFields(programClass, targetClass) && + (!DETAILS || print(programClass, "No unwanted fields?")) && + // The two classes must not introduce any unwanted fields. !introducesUnwantedFields(programClass, targetClass) && !introducesUnwantedFields(targetClass, programClass) && + (!DETAILS || print(programClass, "No shadowed fields?")) && + // The two classes must not shadow each others fields. !shadowsAnyFields(programClass, targetClass) && !shadowsAnyFields(targetClass, programClass) && + (!DETAILS || print(programClass, "No clashing methods?")) && + // The classes must not have clashing methods. !haveAnyIdenticalMethods(programClass, targetClass) && + (!DETAILS || print(programClass, "No abstract methods?")) && + // The classes must not introduce abstract methods, unless // explicitly allowed. (mergeInterfacesAggressively || (!introducesUnwantedAbstractMethods(programClass, targetClass) && !introducesUnwantedAbstractMethods(targetClass, programClass))) && + (!DETAILS || print(programClass, "No overridden methods?")) && + // The classes must not override each others concrete methods. !overridesAnyMethods(programClass, targetClass) && !overridesAnyMethods(targetClass, programClass) && + (!DETAILS || print(programClass, "No shadowed methods?")) && + // The classes must not shadow each others non-private methods. !shadowsAnyMethods(programClass, targetClass) && !shadowsAnyMethods(targetClass, programClass)) { + // We're not actually merging the classes, but only copying the + // contents from the source class to the target class. We'll + // then let all other classes point to it. The shrinking step + // will finally remove the source class. if (DEBUG) { System.out.println("ClassMerger ["+programClass.getName()+"] -> ["+targetClass.getName()+"]"); - System.out.println(" Source interface? ["+((programClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE)!=0)+"]"); - System.out.println(" Target interface? ["+((targetClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE)!=0)+"]"); + System.out.println(" Source interface? ["+((programClass.getAccessFlags() & ClassConstants.ACC_INTERFACE)!=0)+"]"); + System.out.println(" Target interface? ["+((targetClass.getAccessFlags() & ClassConstants.ACC_INTERFACE)!=0)+"]"); System.out.println(" Source subclasses ["+programClass.subClasses+"]"); System.out.println(" Target subclasses ["+targetClass.subClasses+"]"); System.out.println(" Source superclass ["+programClass.getSuperClass().getName()+"]"); @@ -249,17 +293,21 @@ implements ClassVisitor, targetClass.u2accessFlags = ((targetAccessFlags & sourceAccessFlags) & - (ClassConstants.INTERNAL_ACC_INTERFACE | - ClassConstants.INTERNAL_ACC_ABSTRACT)) | + (ClassConstants.ACC_INTERFACE | + ClassConstants.ACC_ABSTRACT)) | ((targetAccessFlags | sourceAccessFlags) & - (ClassConstants.INTERNAL_ACC_PUBLIC | - ClassConstants.INTERNAL_ACC_SUPER | - ClassConstants.INTERNAL_ACC_ANNOTATTION | - ClassConstants.INTERNAL_ACC_ENUM)); - - // Copy over the superclass, unless it's the target class itself. - //if (!targetClass.getName().equals(programClass.getSuperName())) + (ClassConstants.ACC_PUBLIC | + ClassConstants.ACC_SUPER | + ClassConstants.ACC_ANNOTATTION | + ClassConstants.ACC_ENUM)); + + // Copy over the superclass, if it's a non-interface class being + // merged into an interface class. + // However, we're currently never merging in a way that changes the + // superclass. + //if ((programClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) == 0 && + // (targetClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) != 0) //{ // targetClass.u2superClass = // new ConstantAdder(targetClass).addConstant(programClass, programClass.u2superClass); @@ -267,6 +315,9 @@ implements ClassVisitor, // Copy over the interfaces that aren't present yet and that // wouldn't cause loops in the class hierarchy. + // Note that the code shouldn't be iterating over the original + // list at this point. This is why we only add subclasses in + // a separate step. programClass.interfaceConstantsAccept( new ExceptClassConstantFilter(targetClass.getName(), new ImplementedClassConstantFilter(targetClass, @@ -282,10 +333,11 @@ implements ClassVisitor, // Copy over the other attributes. programClass.attributesAccept( - new AttributeNameFilter(new NotMatcher(new OrMatcher(new OrMatcher( - new FixedStringMatcher(ClassConstants.ATTR_SourceFile), - new FixedStringMatcher(ClassConstants.ATTR_InnerClasses)), - new FixedStringMatcher(ClassConstants.ATTR_EnclosingMethod))), + new AttributeNameFilter(new NotMatcher( + new OrMatcher(new FixedStringMatcher(ClassConstants.ATTR_BootstrapMethods), + new OrMatcher(new FixedStringMatcher(ClassConstants.ATTR_SourceFile), + new OrMatcher(new FixedStringMatcher(ClassConstants.ATTR_InnerClasses), + new FixedStringMatcher(ClassConstants.ATTR_EnclosingMethod))))), new AttributeAdder(targetClass, true))); // Update the optimization information of the target class. @@ -314,6 +366,14 @@ implements ClassVisitor, } + private boolean print(ProgramClass programClass, String message) + { + System.out.println("Merge ["+targetClass.getName()+"] <- ["+programClass.getName()+"] "+message); + + return true; + } + + // Small utility methods. /** @@ -352,6 +412,23 @@ implements ClassVisitor, /** + * Returns the set of interface subclasses, not including the given class. + */ + private Set subInterfaces(Clazz clazz, Clazz exceptClass) + { + Set set = new HashSet(); + + // Visit all subclasses, collecting the interface classes. + clazz.hierarchyAccept(false, false, false, true, + new ClassAccessFilter(ClassConstants.ACC_INTERFACE, 0, + new ExceptClassesFilter(new Clazz[] { exceptClass }, + new ClassCollector(set)))); + + return set; + } + + + /** * Returns the set of superclasses and interfaces that are initialized. */ private Set initializedSuperClasses(Clazz clazz) @@ -392,7 +469,7 @@ 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)) + if (!clazz.extends_(ClassConstants.NAME_JAVA_LANG_THROWABLE)) { return Collections.EMPTY_SET; } @@ -410,8 +487,8 @@ implements ClassVisitor, /** - * Returns whether the two given classes have class members with the same - * name and descriptor. + * Returns whether the two given classes have fields with the same + * names and descriptors. */ private boolean haveAnyIdenticalFields(Clazz clazz, Clazz targetClass) { @@ -445,7 +522,7 @@ implements ClassVisitor, MemberCounter counter = new MemberCounter(); // Count all non-static fields in the the source class. - programClass.fieldsAccept(new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_STATIC, + programClass.fieldsAccept(new MemberAccessFilter(0, ClassConstants.ACC_STATIC, counter)); return counter.getCount() > 0; @@ -465,7 +542,7 @@ implements ClassVisitor, clazz.hierarchyAccept(true, false, false, true, new AllFieldVisitor( new SimilarMemberVisitor(targetClass, true, true, true, false, - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, counter)))); return counter.getCount() > 0; @@ -482,9 +559,9 @@ implements ClassVisitor, // 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, + clazz.methodsAccept(new MemberAccessFilter(0, ClassConstants.ACC_ABSTRACT, new SimilarMemberVisitor(targetClass, true, false, false, false, - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_ABSTRACT, + new MemberAccessFilter(0, ClassConstants.ACC_ABSTRACT, counter)))); return counter.getCount() > 0; @@ -501,8 +578,8 @@ implements ClassVisitor, // It's ok if the target class is already abstract and it has at most // the class as a subclass. if ((targetClass.getAccessFlags() & - (ClassConstants.INTERNAL_ACC_ABSTRACT | - ClassConstants.INTERNAL_ACC_INTERFACE)) != 0 && + (ClassConstants.ACC_ABSTRACT | + ClassConstants.ACC_INTERFACE)) != 0 && (targetClass.subClasses == null || isOnlySubClass(clazz, targetClass))) { @@ -514,12 +591,12 @@ implements ClassVisitor, // Collect all abstract methods, and similar abstract methods in the // class hierarchy of the target class. - clazz.methodsAccept(new MemberAccessFilter(ClassConstants.INTERNAL_ACC_ABSTRACT, 0, + clazz.methodsAccept(new MemberAccessFilter(ClassConstants.ACC_ABSTRACT, 0, new MultiMemberVisitor(new MemberVisitor[] { counter, new SimilarMemberVisitor(targetClass, true, true, true, false, - new MemberAccessFilter(ClassConstants.INTERNAL_ACC_ABSTRACT, 0, + new MemberAccessFilter(ClassConstants.ACC_ABSTRACT, 0, new MemberCollector(targetSet))) }))); @@ -537,11 +614,11 @@ implements ClassVisitor, // Visit all non-private non-static methods, counting the ones that are // being overridden in the class hierarchy of the target class. - clazz.methodsAccept(new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC | ClassConstants.INTERNAL_ACC_ABSTRACT, - new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_CLINIT)), - new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_INIT)), + clazz.methodsAccept(new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC | ClassConstants.ACC_ABSTRACT, + new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.METHOD_NAME_CLINIT)), + new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.METHOD_NAME_INIT)), new SimilarMemberVisitor(targetClass, true, true, false, false, - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC | ClassConstants.INTERNAL_ACC_ABSTRACT, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC | ClassConstants.ACC_ABSTRACT, counter)))))); return counter.getCount() > 0; @@ -560,20 +637,20 @@ implements ClassVisitor, // non-private methods in the class hierarchy of the target class. clazz.hierarchyAccept(true, false, false, true, new AllMethodVisitor( - new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0, - new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_INIT)), + new MemberAccessFilter(ClassConstants.ACC_PRIVATE, 0, + new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.METHOD_NAME_INIT)), new SimilarMemberVisitor(targetClass, true, true, true, false, - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, counter)))))); // Visit all static methods, counting the ones that are shadowing // non-private methods in the class hierarchy of the target class. clazz.hierarchyAccept(true, false, false, true, new AllMethodVisitor( - new MemberAccessFilter(ClassConstants.INTERNAL_ACC_STATIC, 0, - new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_CLINIT)), + new MemberAccessFilter(ClassConstants.ACC_STATIC, 0, + new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.METHOD_NAME_CLINIT)), new SimilarMemberVisitor(targetClass, true, true, true, false, - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, counter)))))); return counter.getCount() > 0; @@ -638,4 +715,4 @@ implements ClassVisitor, // 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 3bfd98c..a1f422f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/optimize/peephole/GotoGotoReplacer.java b/src/proguard/optimize/peephole/GotoGotoReplacer.java index 4a490a1..bf7292b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/optimize/peephole/GotoReturnReplacer.java b/src/proguard/optimize/peephole/GotoReturnReplacer.java index b6deec8..aa8ed9f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 31d3d33..ef76f9b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.optimize.peephole; -import proguard.classfile.*; +import proguard.classfile.ProgramClass; import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.*; diff --git a/src/proguard/optimize/peephole/InstructionSequenceConstants.java b/src/proguard/optimize/peephole/InstructionSequenceConstants.java index 4ab9056..df96dda 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -345,43 +345,43 @@ public class InstructionSequenceConstants 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), + new Utf8Constant(ClassConstants.NAME_JAVA_LANG_STRING), + new Utf8Constant(ClassConstants.NAME_JAVA_LANG_STRING_BUFFER), + new Utf8Constant(ClassConstants.NAME_JAVA_LANG_STRING_BUILDER), + new Utf8Constant(ClassConstants.METHOD_NAME_EQUALS), + new Utf8Constant(ClassConstants.METHOD_TYPE_EQUALS), + new Utf8Constant(ClassConstants.METHOD_NAME_LENGTH), + new Utf8Constant(ClassConstants.METHOD_TYPE_LENGTH), + new Utf8Constant(ClassConstants.METHOD_NAME_VALUEOF), + new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_BOOLEAN), + new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_CHAR), + new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_INT), + new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_LONG), + new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_FLOAT), + new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_DOUBLE), + new Utf8Constant(ClassConstants.METHOD_TYPE_VALUEOF_OBJECT), + new Utf8Constant(ClassConstants.METHOD_NAME_INIT), + new Utf8Constant(ClassConstants.METHOD_TYPE_INIT), + new Utf8Constant(ClassConstants.METHOD_TYPE_STRING_VOID), + new Utf8Constant(ClassConstants.METHOD_NAME_TOSTRING), + new Utf8Constant(ClassConstants.METHOD_TYPE_TOSTRING), + new Utf8Constant(ClassConstants.METHOD_NAME_APPEND), + new Utf8Constant(ClassConstants.METHOD_TYPE_BOOLEAN_STRING_BUFFER), + new Utf8Constant(ClassConstants.METHOD_TYPE_CHAR_STRING_BUFFER), + new Utf8Constant(ClassConstants.METHOD_TYPE_INT_STRING_BUFFER), + new Utf8Constant(ClassConstants.METHOD_TYPE_LONG_STRING_BUFFER), + new Utf8Constant(ClassConstants.METHOD_TYPE_FLOAT_STRING_BUFFER), + new Utf8Constant(ClassConstants.METHOD_TYPE_DOUBLE_STRING_BUFFER), + new Utf8Constant(ClassConstants.METHOD_TYPE_STRING_STRING_BUFFER), + new Utf8Constant(ClassConstants.METHOD_TYPE_OBJECT_STRING_BUFFER), + new Utf8Constant(ClassConstants.METHOD_TYPE_BOOLEAN_STRING_BUILDER), + new Utf8Constant(ClassConstants.METHOD_TYPE_CHAR_STRING_BUILDER), + new Utf8Constant(ClassConstants.METHOD_TYPE_INT_STRING_BUILDER), + new Utf8Constant(ClassConstants.METHOD_TYPE_LONG_STRING_BUILDER), + new Utf8Constant(ClassConstants.METHOD_TYPE_FLOAT_STRING_BUILDER), + new Utf8Constant(ClassConstants.METHOD_TYPE_DOUBLE_STRING_BUILDER), + new Utf8Constant(ClassConstants.METHOD_TYPE_STRING_STRING_BUILDER), + new Utf8Constant(ClassConstants.METHOD_TYPE_OBJECT_STRING_BUILDER), }; public static final Instruction[][][] VARIABLE = new Instruction[][][] diff --git a/src/proguard/optimize/peephole/InstructionSequenceReplacer.java b/src/proguard/optimize/peephole/InstructionSequenceReplacer.java index 7ec1a95..6a1d872 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +153,8 @@ implements InstructionVisitor, { // Reset the instruction sequence matcher if the instruction is a branch // target or if it has already been modified. - if (branchTargetFinder.isTarget(offset) || + if ((branchTargetFinder != null && + branchTargetFinder.isTarget(offset)) || codeAttributeEditor.isModified(offset)) { instructionSequenceMatcher.reset(); diff --git a/src/proguard/optimize/peephole/InstructionSequencesReplacer.java b/src/proguard/optimize/peephole/InstructionSequencesReplacer.java index 22fb6cd..9aca05a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 f57281c..420d80a 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -72,7 +72,7 @@ implements MemberVisitor // Make the field private. programField.u2accessFlags = AccessUtil.replaceAccessFlags(programField.u2accessFlags, - ClassConstants.INTERNAL_ACC_PRIVATE); + ClassConstants.ACC_PRIVATE); // Visit the field, if required. if (extraMemberVisitor != null) @@ -88,10 +88,10 @@ implements MemberVisitor // Is the method unmarked? if (NonPrivateMemberMarker.canBeMadePrivate(programMethod)) { - // Make the method private. + // Make the method private and no longer final. programMethod.u2accessFlags = AccessUtil.replaceAccessFlags(programMethod.u2accessFlags, - ClassConstants.INTERNAL_ACC_PRIVATE); + ClassConstants.ACC_PRIVATE); // Visit the method, if required. if (extraMemberVisitor != null) diff --git a/src/proguard/optimize/peephole/MethodFinalizer.java b/src/proguard/optimize/peephole/MethodFinalizer.java index 89174ac..2ce3029 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.optimize.peephole; import proguard.classfile.*; import proguard.classfile.util.*; -import proguard.classfile.visitor.*; +import proguard.classfile.visitor.MemberVisitor; import proguard.optimize.KeepMarker; /** @@ -61,7 +61,7 @@ implements MemberVisitor // Implementations for MemberVisitor. - + public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { String name = programMethod.getName(programClass); @@ -71,17 +71,17 @@ implements MemberVisitor // and its class is final, // or it is not being kept and it is not overridden, // then make it final. - if ((programMethod.u2accessFlags & (ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_STATIC | - ClassConstants.INTERNAL_ACC_FINAL | - ClassConstants.INTERNAL_ACC_ABSTRACT)) == 0 && - !name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) && - ((programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_FINAL) != 0 || + if ((programMethod.u2accessFlags & (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC | + ClassConstants.ACC_FINAL | + ClassConstants.ACC_ABSTRACT)) == 0 && + !name.equals(ClassConstants.METHOD_NAME_INIT) && + ((programClass.u2accessFlags & ClassConstants.ACC_FINAL) != 0 || (!KeepMarker.isKept(programMethod) && (programClass.subClasses == null || !memberFinder.isOverriden(programClass, programMethod))))) { - programMethod.u2accessFlags |= ClassConstants.INTERNAL_ACC_FINAL; + programMethod.u2accessFlags |= ClassConstants.ACC_FINAL; // Visit the method, if required. if (extraMemberVisitor != null) diff --git a/src/proguard/optimize/peephole/MethodInliner.java b/src/proguard/optimize/peephole/MethodInliner.java index 947cd43..5068965 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +30,7 @@ import proguard.classfile.instruction.*; import proguard.classfile.instruction.visitor.InstructionVisitor; import proguard.classfile.util.*; import proguard.classfile.visitor.*; -import proguard.optimize.*; +import proguard.optimize.KeepMarker; import proguard.optimize.info.*; import java.util.*; @@ -155,6 +155,8 @@ implements AttributeVisitor, System.err.println(" Inlined method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]"); } System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")"); + + ex.printStackTrace(); System.err.println("Not inlining this method"); if (DEBUG) @@ -185,7 +187,7 @@ implements AttributeVisitor, exceptionInfoAdder = new ExceptionInfoAdder(targetClass, codeAttributeComposer); estimatedResultingCodeLength = codeAttribute.u4codeLength; inliningMethods.clear(); - uninitializedObjectCount = method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ? 1 : 0; + uninitializedObjectCount = method.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT) ? 1 : 0; inlinedAny = false; codeAttributeComposer.reset(); stackSizeComputer.visitCodeAttribute(clazz, method, codeAttribute); @@ -252,7 +254,7 @@ implements AttributeVisitor, String descriptor = method.getDescriptor(clazz); boolean isStatic = - (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0; + (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0; // Count the number of parameters, taking into account their categories. int parameterCount = ClassUtil.internalMethodParameterCount(descriptor); @@ -287,23 +289,23 @@ implements AttributeVisitor, byte opcode; switch (parameterType.charAt(0)) { - case ClassConstants.INTERNAL_TYPE_BOOLEAN: - case ClassConstants.INTERNAL_TYPE_BYTE: - case ClassConstants.INTERNAL_TYPE_CHAR: - case ClassConstants.INTERNAL_TYPE_SHORT: - case ClassConstants.INTERNAL_TYPE_INT: + case ClassConstants.TYPE_BOOLEAN: + case ClassConstants.TYPE_BYTE: + case ClassConstants.TYPE_CHAR: + case ClassConstants.TYPE_SHORT: + case ClassConstants.TYPE_INT: opcode = InstructionConstants.OP_ISTORE; break; - case ClassConstants.INTERNAL_TYPE_LONG: + case ClassConstants.TYPE_LONG: opcode = InstructionConstants.OP_LSTORE; break; - case ClassConstants.INTERNAL_TYPE_FLOAT: + case ClassConstants.TYPE_FLOAT: opcode = InstructionConstants.OP_FSTORE; break; - case ClassConstants.INTERNAL_TYPE_DOUBLE: + case ClassConstants.TYPE_DOUBLE: opcode = InstructionConstants.OP_DSTORE; break; @@ -471,12 +473,9 @@ implements AttributeVisitor, // Implementations for ConstantVisitor. - public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant) {} - - - public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) + public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant) { - methodrefConstant.referencedMemberAccept(this); + refConstant.referencedMemberAccept(this); } @@ -493,22 +492,23 @@ implements AttributeVisitor, !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 && + // This currently precludes default interface methods, because + // they can't be final. + (accessFlags & (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC | + ClassConstants.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 && + (accessFlags & (ClassConstants.ACC_SYNCHRONIZED | + ClassConstants.ACC_NATIVE | + ClassConstants.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) || +// (!programMethod.getName(programClass).equals(ClassConstants.METHOD_NAME_INIT) || // (programClass.equals(targetClass) && -// targetMethod.getName(targetClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))) && - !programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) && +// targetMethod.getName(targetClass).equals(ClassConstants.METHOD_NAME_INIT))) && + !programMethod.getName(programClass).equals(ClassConstants.METHOD_NAME_INIT) && // Don't inline a method into itself. (!programMethod.equals(targetMethod) || @@ -522,9 +522,10 @@ implements AttributeVisitor, // introducing incompatible constructs. 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) || + // Only inline the method if it doesn't invoke a super method or a + // dynamic method, or if it is in the same class. + (!SuperInvocationMarker.invokesSuperMethods(programMethod) && + !DynamicInvocationMarker.invokesDynamically(programMethod) || programClass.equals(targetClass)) && // Only inline the method if it doesn't branch backward while there @@ -554,9 +555,11 @@ implements AttributeVisitor, // Only inline the method if it comes from the a class with at most // a subset of the initialized superclasses. - (programClass.equals(targetClass) || + ((accessFlags & ClassConstants.ACC_STATIC) == 0 || + programClass.equals(targetClass) || initializedSuperClasses(targetClass).containsAll(initializedSuperClasses(programClass)))) - { boolean oldInlining = inlining; + { + boolean oldInlining = inlining; inlining = true; inliningMethods.push(programMethod); @@ -574,7 +577,7 @@ implements AttributeVisitor, inlining = oldInlining; inliningMethods.pop(); } - else if (programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + else if (programMethod.getName(programClass).equals(ClassConstants.METHOD_NAME_INIT)) { uninitializedObjectCount--; } diff --git a/src/proguard/optimize/peephole/NopRemover.java b/src/proguard/optimize/peephole/NopRemover.java index 9396c40..b869045 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 2a602ee..35c4426 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 b6fcf18..2b8fb10 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java b/src/proguard/optimize/peephole/RetargetedInnerClassAttributeRemover.java index a67c6ff..5d3ccd3 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/TargetClassChanger.java b/src/proguard/optimize/peephole/TargetClassChanger.java index f997e03..a65cad5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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.peephole; import proguard.classfile.*; -import proguard.classfile.editor.*; import proguard.classfile.attribute.*; import proguard.classfile.attribute.annotation.*; import proguard.classfile.attribute.annotation.visitor.*; import proguard.classfile.attribute.visitor.*; import proguard.classfile.constant.*; import proguard.classfile.constant.visitor.ConstantVisitor; -import proguard.classfile.util.*; +import proguard.classfile.editor.*; +import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.*; /** @@ -58,6 +58,9 @@ implements ClassVisitor, public void visitProgramClass(ProgramClass programClass) { + // We're only making changes locally in the class. + // Not all other classes may have been retargeted yet. + // Change the references of the constant pool. programClass.constantPoolEntriesAccept(this); @@ -68,10 +71,41 @@ implements ClassVisitor, // Change the references of the attributes. programClass.attributesAccept(this); - // Is the class itself being retargeted? + // Remove duplicate interfaces and interface classes that have ended + // up pointing to the class itself. + boolean[] delete = null; + for (int index = 0; index < programClass.u2interfacesCount; index++) + { + Clazz interfaceClass = programClass.getInterface(index); + if (interfaceClass != null && + (programClass.equals(interfaceClass) || + containsInterfaceClass(programClass, + index, + interfaceClass))) + { + // Lazily create the array. + if (delete == null) + { + delete = new boolean[programClass.u2interfacesCount]; + } + + delete[index] = true; + } + } + + if (delete != null) + { + new InterfaceDeleter(delete).visitProgramClass(programClass); + } + + // Is the class being retargeted? Clazz targetClass = ClassMerger.getTargetClass(programClass); if (targetClass != null) { + // We're not changing anything special in the superclass and + // interface hierarchy of the retargeted class. The shrinking + // step will remove the class for us. + // Restore the class name. We have to add a new class entry // to avoid an existing entry with the same name being reused. The // names have to be fixed later, based on their referenced classes. @@ -80,29 +114,14 @@ implements ClassVisitor, programClass.getName(), programClass); - // This class will loose all its interfaces. - programClass.u2interfacesCount = 0; - - // This class will loose all its subclasses. + // This class will no longer have any subclasses, because their + // subclasses and interfaces will be retargeted. programClass.subClasses = null; } else { - // Remove interface classes that are pointing to this class. - int newInterfacesCount = 0; - for (int index = 0; index < programClass.u2interfacesCount; index++) - { - Clazz interfaceClass = programClass.getInterface(index); - if (!programClass.equals(interfaceClass)) - { - programClass.u2interfaces[newInterfacesCount++] = - programClass.u2interfaces[index]; - } - } - programClass.u2interfacesCount = newInterfacesCount; - - // Update the subclasses of the superclass and interfaces of the - // target class. + // This class has become the subclass of its possibly new + // superclass and of any new interfaces. ConstantVisitor subclassAdder = new ReferencedClassVisitor( new SubclassFilter(programClass, @@ -279,8 +298,7 @@ implements ClassVisitor, } - - // Implementations for LocalVariableInfoVisitor. + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) { @@ -289,6 +307,7 @@ implements ClassVisitor, updateReferencedClass(localVariableInfo.referencedClass); } + // Implementations for LocalVariableTypeInfoVisitor. public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) @@ -297,6 +316,7 @@ implements ClassVisitor, updateReferencedClasses(localVariableTypeInfo.referencedClasses); } + // Implementations for AnnotationVisitor. public void visitAnnotation(Clazz clazz, Annotation annotation) @@ -379,7 +399,27 @@ implements ClassVisitor, // Small utility methods. - /** + /** + * Returns whether the given class contains the given interface + * class in its first given number of interfaces. + */ + private boolean containsInterfaceClass(Clazz clazz, + int interfaceCount, + Clazz interfaceClass) + { + for (int index = 0; index < interfaceCount; index++) + { + if (interfaceClass.equals(clazz.getInterface(index))) + { + return true; + } + } + + return false; + } + + + /** * Updates the retargeted classes in the given array of classes. */ private void updateReferencedClasses(Clazz[] referencedClasses) diff --git a/src/proguard/optimize/peephole/UnreachableCodeRemover.java b/src/proguard/optimize/peephole/UnreachableCodeRemover.java index 570b3ca..f4e3603 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 8e77716..150c4c5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +41,6 @@ implements AttributeVisitor, private final ExceptionInfoVisitor extraExceptionInfoVisitor; - private final ExceptionInstructionChecker exceptionInstructionChecker = new ExceptionInstructionChecker(); - - /** * Creates a new UnreachableExceptionRemover. */ @@ -123,11 +120,7 @@ implements AttributeVisitor, Instruction instruction = InstructionFactory.create(code, offset); // Check if it may be throwing exceptions. - if (exceptionInstructionChecker.mayThrowExceptions(clazz, - method, - codeAttribute, - offset, - instruction)) + if (instruction.mayThrowExceptions()) { return true; } diff --git a/src/proguard/optimize/peephole/VariableShrinker.java b/src/proguard/optimize/peephole/VariableShrinker.java index 6c05944..6387f1e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -78,7 +78,7 @@ implements AttributeVisitor public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { - if ((method.getAccessFlags() & ClassConstants.INTERNAL_ACC_ABSTRACT) == 0) + if ((method.getAccessFlags() & ClassConstants.ACC_ABSTRACT) == 0) { // Compute the parameter size. int parameterSize = diff --git a/src/proguard/optimize/peephole/VerticalClassMerger.java b/src/proguard/optimize/peephole/VerticalClassMerger.java index 825de94..560e989 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ package proguard.optimize.peephole; import proguard.classfile.ProgramClass; -import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.ClassVisitor; @@ -80,6 +79,7 @@ implements ClassVisitor public void visitProgramClass(ProgramClass programClass) { + // Try inlining all immediate subclasses into this class. programClass.subclassesAccept(new ClassMerger(programClass, allowAccessModification, mergeInterfacesAggressively, diff --git a/src/proguard/preverify/CodePreverifier.java b/src/proguard/preverify/CodePreverifier.java index 7c38259..60e7afe 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,9 +25,9 @@ import proguard.classfile.attribute.*; import proguard.classfile.attribute.preverification.*; import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.editor.*; -import proguard.classfile.instruction.*; +import proguard.classfile.instruction.InstructionConstants; import proguard.classfile.util.SimplifiedVisitor; -import proguard.classfile.visitor.*; +import proguard.classfile.visitor.ClassPrinter; import proguard.evaluation.*; import proguard.evaluation.value.*; import proguard.optimize.evaluation.*; @@ -158,7 +158,7 @@ implements AttributeVisitor partialEvaluator.getVariablesBefore(0)); // Special case: the <init> method. - if (method.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + if (method.getName(programClass).equals(ClassConstants.METHOD_NAME_INIT)) { initialVariables[0] = VerificationTypeFactory.createUninitializedThisType(); } diff --git a/src/proguard/preverify/CodeSubroutineInliner.java b/src/proguard/preverify/CodeSubroutineInliner.java index c1549a3..f0b5775 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 @@ implements AttributeVisitor, private static boolean DEBUG = System.getProperty("csi") != null; //*/ - private final BranchTargetFinder branchTargetFinder = new BranchTargetFinder(); - private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer(true, true); + private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer(true, true, true); private ExceptionInfoVisitor subroutineExceptionInliner = this; private int clipStart = 0; @@ -119,7 +118,7 @@ implements AttributeVisitor, Instruction instruction = InstructionFactory.create(codeAttribute.code, offset); int instructionLength = instruction.length(offset); - // Is this returning subroutine? + // Is this a returning subroutine? if (branchTargetFinder.isSubroutine(offset) && branchTargetFinder.isSubroutineReturning(offset)) { @@ -228,8 +227,22 @@ implements AttributeVisitor, public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) { - // Append the instruction. - codeAttributeComposer.appendInstruction(offset, instruction); + if (branchTargetFinder.isSubroutineStart(offset)) + { + if (DEBUG) + { + System.out.println(" Replacing first subroutine instruction "+instruction.toString(offset)+" by a label"); + } + + // Append a label at this offset instead of saving the subroutine + // return address. + codeAttributeComposer.appendLabel(offset); + } + else + { + // Append the instruction. + codeAttributeComposer.appendInstruction(offset, instruction); + } } @@ -268,7 +281,7 @@ implements AttributeVisitor, { if (DEBUG) { - System.out.println(" Replacing first subroutine instruction at ["+offset+"] by a label"); + System.out.println(" Replacing first subroutine instruction "+variableInstruction.toString(offset)+" by a label"); } // Append a label at this offset instead of saving the subroutine diff --git a/src/proguard/preverify/Preverifier.java b/src/proguard/preverify/Preverifier.java index da9649b..59dad7f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,20 +54,15 @@ public class Preverifier programClassPool.classesAccept(new ClassCleaner()); // Preverify all methods. - ClassVisitor preverifier = + // Classes for JME must be preverified. + // Classes for JSE 6 may optionally be preverified. + // Classes for JSE 7 or higher must be preverified. + programClassPool.classesAccept( + new ClassVersionFilter(configuration.microEdition ? + ClassConstants.CLASS_VERSION_1_0 : + ClassConstants.CLASS_VERSION_1_6, new AllMethodVisitor( new AllAttributeVisitor( - new CodePreverifier(configuration.microEdition))); - - // 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, - preverifier); - } - - programClassPool.classesAccept(preverifier); + new CodePreverifier(configuration.microEdition))))); } } diff --git a/src/proguard/preverify/SubroutineInliner.java b/src/proguard/preverify/SubroutineInliner.java index e21c469..b069612 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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 SubroutineInliner if (!configuration.microEdition) { inliner = - new ClassVersionFilter(ClassConstants.INTERNAL_CLASS_VERSION_1_6, + new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_6, inliner); } diff --git a/src/proguard/retrace/ReTrace.java b/src/proguard/retrace/ReTrace.java index 91ab2a7..fae47e5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +41,7 @@ implements MappingProcessor private static final String VERBOSE_OPTION = "-verbose"; - public static final String STACK_TRACE_EXPRESSION = "(?:.*?\\bat\\s+%c.%m\\s*\\(.*?(?::%l)?\\)\\s*)|(?:(?:.*?[:\"]\\s+)?%c(?::.*)?)"; + public static final String STACK_TRACE_EXPRESSION = "(?:.*?\\bat\\s+%c\\.%m\\s*\\(.*?(?::%l)?\\)\\s*)|(?:(?:.*?[:\"]\\s+)?%c(?::.*)?)"; 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"; @@ -112,7 +112,7 @@ implements MappingProcessor MappingReader mappingReader = new MappingReader(mappingFile); mappingReader.pump(this); - + // Construct the regular expression. StringBuffer expressionBuffer = new StringBuffer(regularExpression.length() + 32); char[] expressionTypes = new char[32]; int expressionTypeCount = 0; @@ -173,39 +173,42 @@ implements MappingProcessor Pattern pattern = Pattern.compile(expressionBuffer.toString()); - // Read the stack trace file. + // Open the stack trace file. LineNumberReader reader = new LineNumberReader(stackTraceFile == null ? (Reader)new InputStreamReader(System.in) : (Reader)new BufferedReader(new FileReader(stackTraceFile))); - + // Read and process the lines of the stack trace. try { - StringBuffer outLine = new StringBuffer(256); - List extraOutLines = new ArrayList(); + StringBuffer outLine = new StringBuffer(256); + List extraOutLines = new ArrayList(); String className = null; - // Read the line in the stack trace. + // Read all lines from the stack trace. while (true) { + // Read a line. String line = reader.readLine(); if (line == null) { break; } + // Try to match it against the regular expression. Matcher matcher = pattern.matcher(line); if (matcher.matches()) { + // The line matched the regular expression. int lineNumber = 0; String type = null; String arguments = null; - // Figure out a class name, line number, type, and - // arguments beforehand. + // Extract a class name, a line number, a type, and + // arguments. for (int expressionTypeIndex = 0; expressionTypeIndex < expressionTypeCount; expressionTypeIndex++) { int startIndex = matcher.start(expressionTypeIndex + 1); @@ -239,7 +242,9 @@ implements MappingProcessor } } - // Actually construct the output line. + // Deconstruct the input line and reconstruct the output + // line. Also collect any additional output lines for this + // line. int lineIndex = 0; outLine.setLength(0); @@ -253,9 +258,10 @@ implements MappingProcessor int endIndex = matcher.end(expressionTypeIndex + 1); String match = matcher.group(expressionTypeIndex + 1); - // Copy a literal piece of input line. + // Copy a literal piece of the input line. outLine.append(line.substring(lineIndex, startIndex)); + // Copy a matched and translated piece of the input line. char expressionType = expressionTypes[expressionTypeIndex]; switch (expressionType) { @@ -309,10 +315,10 @@ implements MappingProcessor } } - // Copy the last literal piece of input line. + // Copy the last literal piece of the input line. outLine.append(line.substring(lineIndex)); - // Print out the main line. + // Print out the processed line. System.out.println(outLine); // Print out any additional lines. @@ -323,6 +329,7 @@ implements MappingProcessor } else { + // The line didn't match the regular expression. // Print out the original line. System.out.println(line); } diff --git a/src/proguard/shrink/AnnotationUsageMarker.java b/src/proguard/shrink/AnnotationUsageMarker.java index b9051a0..2cc0266 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/shrink/ClassShrinker.java b/src/proguard/shrink/ClassShrinker.java index f590c63..3c3a55e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +50,10 @@ implements ClassVisitor, { private final UsageMarker usageMarker; - private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE]; - private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper(); + private int[] constantIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE]; + private int[] bootstrapMethodIndexMap = new int[ClassConstants.TYPICAL_CONSTANT_POOL_SIZE]; + private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper(); + private final BootstrapMethodRemapper bootstrapMethodRemapper = new BootstrapMethodRemapper(); /** @@ -71,10 +73,13 @@ implements ClassVisitor, { // Shrink the arrays for constant pool, interfaces, fields, methods, // and class attributes. - programClass.u2interfacesCount = - shrinkConstantIndexArray(programClass.constantPool, - programClass.u2interfaces, - programClass.u2interfacesCount); + if (programClass.u2interfacesCount > 0) + { + new InterfaceDeleter(shrinkFlags(programClass.constantPool, + programClass.u2interfaces, + programClass.u2interfacesCount)) + .visitProgramClass(programClass); + } // Shrinking the constant pool also sets up an index map. int newConstantPoolCount = @@ -109,8 +114,11 @@ implements ClassVisitor, constantPoolRemapper.visitProgramClass(programClass); } - // Remove the unused interfaces from the class signature. - programClass.attributesAccept(new SignatureShrinker()); + // Replace any unused classes in the signatures. + MySignatureCleaner signatureCleaner = new MySignatureCleaner(); + programClass.fieldsAccept(new AllAttributeVisitor(signatureCleaner)); + programClass.methodsAccept(new AllAttributeVisitor(signatureCleaner)); + programClass.attributesAccept(signatureCleaner); // Compact the extra field pointing to the subclasses of this class. programClass.subClasses = @@ -150,9 +158,18 @@ implements ClassVisitor, public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute) { // Shrink the array of BootstrapMethodInfo objects. - bootstrapMethodsAttribute.u2bootstrapMethodsCount = - shrinkArray(bootstrapMethodsAttribute.bootstrapMethods, - bootstrapMethodsAttribute.u2bootstrapMethodsCount); + int newBootstrapMethodsCount = + shrinkBootstrapMethodArray(bootstrapMethodsAttribute.bootstrapMethods, + bootstrapMethodsAttribute.u2bootstrapMethodsCount); + + if (newBootstrapMethodsCount < bootstrapMethodsAttribute.u2bootstrapMethodsCount) + { + bootstrapMethodsAttribute.u2bootstrapMethodsCount = newBootstrapMethodsCount; + + // Remap all constant pool references. + bootstrapMethodRemapper.setConstantIndexMap(bootstrapMethodIndexMap); + clazz.constantPoolEntriesAccept(bootstrapMethodRemapper); + } } @@ -228,7 +245,7 @@ implements ClassVisitor, public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) { // Loop over all parameters. - for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++) + for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u1parametersCount; parameterIndex++) { // Shrink the parameter annotations array. parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex] = @@ -256,10 +273,10 @@ implements ClassVisitor, /** - * This AttributeVisitor updates the Utf8 constants of class signatures, - * removing any unused interfaces. + * This AttributeVisitor updates the Utf8 constants of signatures + * of classes, fields, and methods. */ - private class SignatureShrinker + private class MySignatureCleaner extends SimplifiedVisitor implements AttributeVisitor { @@ -271,55 +288,41 @@ implements ClassVisitor, Clazz[] referencedClasses = signatureAttribute.referencedClasses; if (referencedClasses != null) { - // Go over the generic definitions, superclass and implemented interfaces. - String signature = clazz.getString(signatureAttribute.u2signatureIndex); + // Go over the classes in the signature. + String signature = signatureAttribute.getSignature(clazz); + + DescriptorClassEnumeration classEnumeration = + new DescriptorClassEnumeration(signature); - InternalTypeEnumeration internalTypeEnumeration = - new InternalTypeEnumeration(signature); + int referencedClassIndex = 0; + // Start construction a new signature. StringBuffer newSignatureBuffer = new StringBuffer(); - int referencedClassIndex = 0; - int newReferencedClassIndex = 0; + newSignatureBuffer.append(classEnumeration.nextFluff()); - while (internalTypeEnumeration.hasMoreTypes()) + while (classEnumeration.hasMoreClassNames()) { - // Consider the classes referenced by this signature. - String type = internalTypeEnumeration.nextType(); - int classCount = new DescriptorClassEnumeration(type).classCount(); + String className = classEnumeration.nextClassName(); + // Replace the class name if it is unused. Clazz referencedClass = referencedClasses[referencedClassIndex]; - if (referencedClass == null || - usageMarker.isUsed(referencedClass)) + if (referencedClass != null && + !usageMarker.isUsed(referencedClass)) { - // Append the superclass or interface. - newSignatureBuffer.append(type); - - // Copy the referenced classes. - for (int counter = 0; counter < classCount; counter++) - { - referencedClasses[newReferencedClassIndex++] = - referencedClasses[referencedClassIndex++]; - } - } - else - { - // Skip the referenced classes. - referencedClassIndex += classCount; + className = ClassConstants.NAME_JAVA_LANG_OBJECT; + + referencedClasses[referencedClassIndex] = null; } - } - if (newReferencedClassIndex < referencedClassIndex) - { - // Update the signature. - ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString()); + referencedClassIndex++; - // Clear the unused entries. - while (newReferencedClassIndex < referencedClassIndex) - { - referencedClasses[newReferencedClassIndex++] = null; - } + newSignatureBuffer.append(className); + newSignatureBuffer.append(classEnumeration.nextFluff()); } + + // Update the signature. + ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString()); } } } @@ -353,7 +356,8 @@ implements ClassVisitor, /** * Removes all entries that are not marked as being used from the given - * constant pool. + * constant pool. Creates a map from the old indices to the new indices + * as a side effect. * @return the new number of entries. */ private int shrinkConstantPool(Constant[] constantPool, int length) @@ -373,7 +377,8 @@ implements ClassVisitor, Constant constant = constantPool[index]; - // Don't update the flag if this is the second half of a long entry. + // Is the constant being used? Don't update the flag if this is the + // second half of a long entry. if (constant != null) { isUsed = usageMarker.isUsed(constant); @@ -381,8 +386,17 @@ implements ClassVisitor, if (isUsed) { + // Remember the new index. + constantIndexMap[index] = counter; + + // Shift the constant pool entry. constantPool[counter++] = constant; } + else + { + // Remember an invalid index. + constantIndexMap[index] = -1; + } } // Clear the remaining constant pool elements. @@ -393,6 +407,28 @@ implements ClassVisitor, /** + * Creates an array marking unused constant pool entries for all the + * elements in the given array of constant pool indices. + * @return an array of flags indicating unused elements. + */ + private boolean[] shrinkFlags(Constant[] constantPool, int[] array, int length) + { + boolean[] unused = new boolean[length]; + + // Shift the used objects together. + for (int index = 0; index < length; index++) + { + if (!usageMarker.isUsed(constantPool[array[index]])) + { + unused[index] = true; + } + } + + return unused; + } + + + /** * Removes all indices that point to unused constant pool entries * from the given array. * @return the new number of indices. @@ -451,6 +487,49 @@ implements ClassVisitor, /** + * Removes all entries that are not marked as being used from the given + * array of bootstrap methods. Creates a map from the old indices to the + * new indices as a side effect. + * @return the new number of entries. + */ + private int shrinkBootstrapMethodArray(BootstrapMethodInfo[] bootstrapMethods, int length) + { + if (bootstrapMethodIndexMap.length < length) + { + bootstrapMethodIndexMap = new int[length]; + } + + int counter = 0; + + // Shift the used bootstrap methods together. + for (int index = 0; index < length; index++) + { + BootstrapMethodInfo bootstrapMethod = bootstrapMethods[index]; + + // Is the entry being used? + if (usageMarker.isUsed(bootstrapMethod)) + { + // Remember the new index. + bootstrapMethodIndexMap[index] = counter; + + // Shift the entry. + bootstrapMethods[counter++] = bootstrapMethod; + } + else + { + // Remember an invalid index. + bootstrapMethodIndexMap[index] = -1; + } + } + + // Clear the remaining bootstrap methods. + Arrays.fill(bootstrapMethods, counter, length, null); + + return counter; + } + + + /** * Removes all VisitorAccepter objects that are not marked as being used * from the given array. * @return the new number of VisitorAccepter objects. @@ -462,9 +541,11 @@ implements ClassVisitor, // Shift the used objects together. for (int index = 0; index < length; index++) { - if (usageMarker.isUsed(array[index])) + VisitorAccepter visitorAccepter = array[index]; + + if (usageMarker.isUsed(visitorAccepter)) { - array[counter++] = array[index]; + array[counter++] = visitorAccepter; } } diff --git a/src/proguard/shrink/InnerUsageMarker.java b/src/proguard/shrink/InnerUsageMarker.java index 6d77e81..a65b519 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 240838e..ecdf678 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 index 573d8f6..3d6ef27 100644 --- a/src/proguard/shrink/LocalVariableTypeUsageMarker.java +++ b/src/proguard/shrink/LocalVariableTypeUsageMarker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,6 @@ * 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.*; @@ -48,7 +47,7 @@ implements AttributeVisitor, { private final UsageMarker usageMarker; - // Fields acting as a return parameters for several methods. + // Fields acting as return values for several visitor methods. private boolean tableUsed; private boolean variableInfoUsed; diff --git a/src/proguard/shrink/ShortestUsageMark.java b/src/proguard/shrink/ShortestUsageMark.java index e2df7fa..80d1c8f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 1ac6e7e..6718e68 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 8740b9f..c6075ea 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/shrink/Shrinker.java b/src/proguard/shrink/Shrinker.java index 0472c3d..72f878b 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +73,8 @@ public class Shrinker new MultiClassVisitor(new ClassVisitor[] { usageMarker, - new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_INIT, - ClassConstants.INTERNAL_METHOD_TYPE_INIT, + new NamedMethodVisitor(ClassConstants.METHOD_NAME_INIT, + ClassConstants.METHOD_TYPE_INIT, usageMarker) }); @@ -88,6 +88,7 @@ public class Shrinker // Mark the seeds. programClassPool.accept(classPoolvisitor); libraryClassPool.accept(classPoolvisitor); + libraryClassPool.classesAccept(usageMarker); // Mark interfaces that have to be kept. programClassPool.classesAccept(new InterfaceUsageMarker(usageMarker)); @@ -100,7 +101,6 @@ public class Shrinker { new InnerUsageMarker(usageMarker), new AnnotationUsageMarker(usageMarker), - new SignatureUsageMarker(usageMarker), new LocalVariableTypeUsageMarker(usageMarker) })))); @@ -146,7 +146,7 @@ public class Shrinker } } - // Discard unused program classes. + // Clean up used program classes and discard unused program classes. int originalProgramClassPoolSize = programClassPool.size(); ClassPool newProgramClassPool = new ClassPool(); @@ -160,6 +160,10 @@ public class Shrinker programClassPool.clear(); + // Clean up library classes. + libraryClassPool.classesAccept( + new ClassShrinker(usageMarker)); + // Check if we have at least some output classes. int newProgramClassPoolSize = newProgramClassPool.size(); if (newProgramClassPoolSize == 0) diff --git a/src/proguard/shrink/SignatureUsageMarker.java b/src/proguard/shrink/SignatureUsageMarker.java index 9c5cd4d..91bfcdd 100644 --- a/src/proguard/shrink/SignatureUsageMarker.java +++ b/src/proguard/shrink/SignatureUsageMarker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,8 +23,8 @@ package proguard.shrink; import proguard.classfile.*; import proguard.classfile.attribute.*; -import proguard.classfile.attribute.visitor.*; -import proguard.classfile.constant.*; +import proguard.classfile.attribute.visitor.AttributeVisitor; +import proguard.classfile.constant.Constant; import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.ClassVisitor; @@ -67,8 +67,8 @@ implements AttributeVisitor, public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) { - // Only keep the signature if all of its classes are used. - attributeUsed = true; + // Only keep the signature if any of its classes are used. + attributeUsed = false; signatureAttribute.referencedClassesAccept(this); if (attributeUsed) @@ -84,15 +84,18 @@ implements AttributeVisitor, // Implementations for ClassVisitor. - public void visitLibraryClass(LibraryClass libraryClass) {} + public void visitLibraryClass(LibraryClass libraryClass) + { + attributeUsed = true; + } public void visitProgramClass(ProgramClass programClass) { // Don't keep the signature if one of its classes is not used. - if (!usageMarker.isUsed(programClass)) + if (usageMarker.isUsed(programClass)) { - attributeUsed = false; + attributeUsed = true; } } diff --git a/src/proguard/shrink/UsageMarker.java b/src/proguard/shrink/UsageMarker.java index 51210b5..88a88fd 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -52,6 +52,7 @@ implements ClassVisitor, ExceptionInfoVisitor, StackMapFrameVisitor, VerificationTypeVisitor, + ParameterInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, // AnnotationVisitor, @@ -71,8 +72,8 @@ implements ClassVisitor, 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, + new NamedMethodVisitor(ClassConstants.METHOD_NAME_INIT, + ClassConstants.METHOD_TYPE_INIT, this))); // Implementations for ClassVisitor. @@ -105,8 +106,8 @@ implements ClassVisitor, interfaceUsageMarker); // Explicitly mark the <clinit> method, if it's not empty. - programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT, - ClassConstants.INTERNAL_METHOD_TYPE_CLINIT, + programClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT, + ClassConstants.METHOD_TYPE_CLINIT, nonEmptyMethodUsageMarker); // Process all class members that have already been marked as possibly used. @@ -355,18 +356,18 @@ implements ClassVisitor, { int accessFlags = method.getAccessFlags(); if ((accessFlags & - (ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_STATIC)) == 0 && + (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC)) == 0 && !ClassUtil.isInitializer(method.getName(clazz))) { // We can skip private and static methods in the hierarchy, and // also abstract methods, unless they might widen a current // non-public access. int requiredUnsetAccessFlags = - ClassConstants.INTERNAL_ACC_PRIVATE | - ClassConstants.INTERNAL_ACC_STATIC | - ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) == 0 ? 0 : - ClassConstants.INTERNAL_ACC_ABSTRACT); + ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC | + ((accessFlags & ClassConstants.ACC_PUBLIC) == 0 ? 0 : + ClassConstants.ACC_ABSTRACT); clazz.accept(new ConcreteClassDownTraveler( new ClassHierarchyTraveler(true, true, false, true, @@ -448,6 +449,9 @@ implements ClassVisitor, markConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex); + // Mark the referenced descriptor classes. + invokeDynamicConstant.referencedClassesAccept(this); + // Mark the bootstrap methods attribute. clazz.attributesAccept(new MyBootStrapMethodUsageMarker(invokeDynamicConstant.u2bootstrapMethodAttributeIndex)); } @@ -507,6 +511,9 @@ implements ClassVisitor, markAsUsed(methodTypeConstant); markConstant(clazz, methodTypeConstant.u2descriptorIndex); + + // Mark the referenced descriptor classes. + methodTypeConstant.referencedClassesAccept(this); } } @@ -553,11 +560,11 @@ implements ClassVisitor, markAsUsed(bootstrapMethodsAttribute); markConstant(clazz, bootstrapMethodsAttribute.u2attributeNameIndex); - - bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz, - bootstrapMethodIndex, - this); } + + bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz, + bootstrapMethodIndex, + this); } @@ -658,12 +665,15 @@ implements ClassVisitor, public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) { - // 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); + markAsUsed(signatureAttribute); + + markConstant(clazz, signatureAttribute.u2attributeNameIndex); + markConstant(clazz, signatureAttribute.u2signatureIndex); + + // Don't mark the referenced classes. We'll clean them up in + // ClassShrinker, if they appear unused. + //// Mark the classes referenced in the descriptor string. + //signatureAttribute.referencedClassesAccept(this); } @@ -676,6 +686,17 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + markAsUsed(methodParametersAttribute); + + markConstant(clazz, methodParametersAttribute.u2attributeNameIndex); + + // Mark the constant pool entries referenced by the parameter information. + methodParametersAttribute.parametersAccept(clazz, method, this); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { markAsUsed(exceptionsAttribute); @@ -787,12 +808,12 @@ implements ClassVisitor, { // Don't mark the attribute and its contents yet. We may mark them later, // in AnnotationUsageMarker. -// markAsUsed(annotationDefaultAttribute); -// -// markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex); -// -// // Mark the constant pool entries referenced by the element value. -// annotationDefaultAttribute.defaultValueAccept(clazz, this); + //markAsUsed(annotationDefaultAttribute); + // + //markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex); + // + //// Mark the constant pool entries referenced by the element value. + //annotationDefaultAttribute.defaultValueAccept(clazz, this); } @@ -865,6 +886,14 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + markConstant(clazz, parameterInfo.u2nameIndex); + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) diff --git a/src/proguard/shrink/UsagePrinter.java b/src/proguard/shrink/UsagePrinter.java index 69df7fa..2b1a9d8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,7 +138,6 @@ implements ClassVisitor, { printClassNameHeader(); - ps.print("===="); ps.print(" "); programMethod.attributesAccept(programClass, this); ps.println(ClassUtil.externalFullMethodDescription( diff --git a/src/proguard/shrink/UsedClassFilter.java b/src/proguard/shrink/UsedClassFilter.java index 7630b0b..93548c5 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 f1a9c75..d5ff5b0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/util/AndMatcher.java b/src/proguard/util/AndMatcher.java index 1aa3726..2322bd0 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 index 8584700..f2bcfe1 100644 --- a/src/proguard/util/ArrayUtil.java +++ b/src/proguard/util/ArrayUtil.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -113,6 +113,36 @@ public class ArrayUtil /** + * Returns whether the elements of the two given arrays are the same, or + * both arrays are null. + * @param array1 the first array. + * @param array2 the second array. + * @return whether the elements are the same. + */ + public static boolean equalOrNull(Object[] array1, Object[] array2) + { + return array1 == null ? array2 == null : + equalOrNull(array1, array2, array1.length); + } + + + /** + * Returns whether the elements of the two given arrays are the same, or + * both arrays are null. + * @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 equalOrNull(Object[] array1, Object[] array2, int size) + { + return array1 == null ? array2 == null : + array2 != null && + equal(array1, array2, size); + } + + + /** * 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. @@ -189,6 +219,31 @@ public class ArrayUtil /** + * Returns a hash code for the elements of the given array, or 0 if it is + * null. + * @param array the array. + * @return a hash code. + */ + public static int hashCodeOrNull(Object[] array) + { + return array == null ? 0 : hashCode(array, array.length); + } + + + /** + * Returns a hash code for the elements of the given array, or 0 if it is + * null. + * @param array the array. + * @param size the size of the array to be taken into account. + * @return a hash code. + */ + public static int hashCodeOrNull(Object[] array, int size) + { + return array == null ? 0 : hashCode(array, size); + } + + + /** * Compares the elements of the two given arrays. * @param array1 the first array. * @param size1 the size of the first array. diff --git a/src/proguard/util/ClassNameParser.java b/src/proguard/util/ClassNameParser.java index 22a0703..a756eba 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is 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,15 +43,15 @@ public class ClassNameParser implements StringParser { private static final char[] INTERNAL_PRIMITIVE_TYPES = new char[] { - ClassConstants.INTERNAL_TYPE_VOID, - ClassConstants.INTERNAL_TYPE_BOOLEAN, - ClassConstants.INTERNAL_TYPE_BYTE, - ClassConstants.INTERNAL_TYPE_CHAR, - ClassConstants.INTERNAL_TYPE_SHORT, - ClassConstants.INTERNAL_TYPE_INT, - ClassConstants.INTERNAL_TYPE_LONG, - ClassConstants.INTERNAL_TYPE_FLOAT, - ClassConstants.INTERNAL_TYPE_DOUBLE, + ClassConstants.TYPE_VOID, + ClassConstants.TYPE_BOOLEAN, + ClassConstants.TYPE_BYTE, + ClassConstants.TYPE_CHAR, + ClassConstants.TYPE_SHORT, + ClassConstants.TYPE_INT, + ClassConstants.TYPE_LONG, + ClassConstants.TYPE_FLOAT, + ClassConstants.TYPE_DOUBLE, }; @@ -98,7 +98,7 @@ public class ClassNameParser implements StringParser // remainder of the string. nextMatcher = new VariableStringMatcher(null, - new char[] { ClassConstants.INTERNAL_TYPE_CLASS_END }, + new char[] { ClassConstants.TYPE_CLASS_END }, 0, Integer.MAX_VALUE, parse(regularExpression.substring(index + 2))); @@ -112,7 +112,7 @@ public class ClassNameParser implements StringParser // remainder of the string. nextMatcher = new VariableStringMatcher(null, - new char[] { ClassConstants.INTERNAL_TYPE_CLASS_END, ClassConstants.INTERNAL_PACKAGE_SEPARATOR }, + new char[] { ClassConstants.TYPE_CLASS_END, ClassConstants.PACKAGE_SEPARATOR }, 0, Integer.MAX_VALUE, parse(regularExpression.substring(index + 1))); @@ -126,7 +126,7 @@ public class ClassNameParser implements StringParser // remainder of the string. nextMatcher = new VariableStringMatcher(null, - new char[] { ClassConstants.INTERNAL_TYPE_CLASS_END, ClassConstants.INTERNAL_PACKAGE_SEPARATOR }, + new char[] { ClassConstants.TYPE_CLASS_END, ClassConstants.PACKAGE_SEPARATOR }, 1, 1, parse(regularExpression.substring(index + 1))); @@ -158,14 +158,13 @@ public class ClassNameParser implements StringParser // Small utility methods. - /** * Creates a StringMatcher that matches any type (class or primitive type, * array or non-array) and then the given matcher. */ private VariableStringMatcher createAnyTypeMatcher(StringMatcher nextMatcher) { - return new VariableStringMatcher(new char[] { ClassConstants.INTERNAL_TYPE_ARRAY }, + return new VariableStringMatcher(new char[] { ClassConstants.TYPE_ARRAY }, null, 0, 255, @@ -175,15 +174,15 @@ public class ClassNameParser implements StringParser 1, 1, nextMatcher), - new VariableStringMatcher(new char[] { ClassConstants.INTERNAL_TYPE_CLASS_START }, + new VariableStringMatcher(new char[] { ClassConstants.TYPE_CLASS_START }, null, 1, 1, new VariableStringMatcher(null, - new char[] { ClassConstants.INTERNAL_TYPE_CLASS_END }, + new char[] { ClassConstants.TYPE_CLASS_END }, 0, Integer.MAX_VALUE, - new VariableStringMatcher(new char[] { ClassConstants.INTERNAL_TYPE_CLASS_END }, + new VariableStringMatcher(new char[] { ClassConstants.TYPE_CLASS_END }, null, 1, 1, diff --git a/src/proguard/util/ConstantMatcher.java b/src/proguard/util/ConstantMatcher.java index 8c0f1e1..d8b9223 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 f07c666..65c518d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 eeb627a..5ee9175 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 9ec6d22..a988ff8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 2f02271..bc81343 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 e07bff0..cad117d 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 b3b4518..c8e3dc4 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/util/ListUtil.java b/src/proguard/util/ListUtil.java index 18bdce2..9004e69 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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/NameParser.java b/src/proguard/util/NameParser.java index f25d52e..30d7c5f 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 af539d0..7820cc8 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 index c5de36a..4d2c159 100644 --- a/src/proguard/util/ObjectUtil.java +++ b/src/proguard/util/ObjectUtil.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/util/OrMatcher.java b/src/proguard/util/OrMatcher.java index 7ad85c4..b51809c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 8650ccc..3674a3e 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 146dbfc..91fae4c 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 39d04d5..8e49293 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 5a07c2a..e83ed05 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute 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 b6f9ace..d8bbd56 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-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free |