proguard.obfuscate.Obfuscator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of proguard-base Show documentation
Show all versions of proguard-base Show documentation
ProGuard is a free shrinker, optimizer, obfuscator, and preverifier for Java bytecode
/*
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
* Copyright (c) 2002-2022 Guardsquare NV
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package proguard.obfuscate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import proguard.AppView;
import proguard.Configuration;
import proguard.classfile.AccessConstants;
import proguard.classfile.VersionConstants;
import proguard.classfile.attribute.Attribute;
import proguard.classfile.attribute.visitor.AllAttributeVisitor;
import proguard.classfile.attribute.visitor.AllBootstrapMethodInfoVisitor;
import proguard.classfile.attribute.visitor.AllInnerClassesInfoVisitor;
import proguard.classfile.attribute.visitor.AttributeNameFilter;
import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.attribute.visitor.MultiAttributeVisitor;
import proguard.classfile.attribute.visitor.NonEmptyAttributeFilter;
import proguard.classfile.attribute.visitor.RequiredAttributeFilter;
import proguard.classfile.constant.Constant;
import proguard.classfile.constant.visitor.AllBootstrapMethodArgumentVisitor;
import proguard.classfile.constant.visitor.AllConstantVisitor;
import proguard.classfile.constant.visitor.ConstantTagFilter;
import proguard.classfile.editor.AccessFixer;
import proguard.classfile.editor.BridgeMethodFixer;
import proguard.classfile.editor.ClassReferenceFixer;
import proguard.classfile.editor.ConstantPoolShrinker;
import proguard.classfile.editor.InnerClassesAccessFixer;
import proguard.classfile.editor.MemberReferenceFixer;
import proguard.classfile.kotlin.visitor.AllConstructorVisitor;
import proguard.classfile.kotlin.visitor.AllFunctionVisitor;
import proguard.classfile.kotlin.visitor.AllPropertyVisitor;
import proguard.classfile.kotlin.visitor.AllTypeVisitor;
import proguard.classfile.kotlin.visitor.AllValueParameterVisitor;
import proguard.classfile.kotlin.visitor.KotlinClassToDefaultImplsClassVisitor;
import proguard.classfile.kotlin.visitor.KotlinFunctionToDefaultMethodVisitor;
import proguard.classfile.kotlin.visitor.KotlinMetadataToClazzVisitor;
import proguard.classfile.kotlin.visitor.MethodToKotlinFunctionVisitor;
import proguard.classfile.kotlin.visitor.MultiKotlinMetadataVisitor;
import proguard.classfile.kotlin.visitor.ReferencedKotlinMetadataVisitor;
import proguard.classfile.kotlin.visitor.filter.KotlinClassKindFilter;
import proguard.classfile.kotlin.visitor.filter.KotlinSyntheticClassKindFilter;
import proguard.classfile.util.MethodLinker;
import proguard.classfile.util.WarningLogger;
import proguard.classfile.util.WarningPrinter;
import proguard.classfile.visitor.AllMemberVisitor;
import proguard.classfile.visitor.AllMethodVisitor;
import proguard.classfile.visitor.BottomClassFilter;
import proguard.classfile.visitor.ClassAccessFilter;
import proguard.classfile.visitor.ClassCounter;
import proguard.classfile.visitor.ClassHierarchyTraveler;
import proguard.classfile.visitor.ClassProcessingFlagFilter;
import proguard.classfile.visitor.ClassVersionFilter;
import proguard.classfile.visitor.ClassVisitor;
import proguard.classfile.visitor.DynamicReturnedClassVisitor;
import proguard.classfile.visitor.FunctionalInterfaceFilter;
import proguard.classfile.visitor.MemberAccessFilter;
import proguard.classfile.visitor.MemberCounter;
import proguard.classfile.visitor.MemberProcessingFlagFilter;
import proguard.classfile.visitor.MethodFilter;
import proguard.classfile.visitor.MultiClassVisitor;
import proguard.classfile.visitor.ProgramClassFilter;
import proguard.classfile.visitor.ProgramMemberFilter;
import proguard.classfile.visitor.ReferencedClassVisitor;
import proguard.fixer.kotlin.KotlinAnnotationFlagFixer;
import proguard.obfuscate.kotlin.KotlinAliasNameObfuscator;
import proguard.obfuscate.kotlin.KotlinAliasReferenceFixer;
import proguard.obfuscate.kotlin.KotlinCallableReferenceFixer;
import proguard.obfuscate.kotlin.KotlinCompanionEqualizer;
import proguard.obfuscate.kotlin.KotlinDefaultImplsMethodNameEqualizer;
import proguard.obfuscate.kotlin.KotlinDefaultMethodNameEqualizer;
import proguard.obfuscate.kotlin.KotlinIntrinsicsReplacementSequences;
import proguard.obfuscate.kotlin.KotlinModuleNameObfuscator;
import proguard.obfuscate.kotlin.KotlinMultiFileFacadeFixer;
import proguard.obfuscate.kotlin.KotlinObjectFixer;
import proguard.obfuscate.kotlin.KotlinPropertyNameObfuscator;
import proguard.obfuscate.kotlin.KotlinPropertyRenamer;
import proguard.obfuscate.kotlin.KotlinSourceDebugExtensionAttributeObfuscator;
import proguard.obfuscate.kotlin.KotlinSyntheticClassFixer;
import proguard.obfuscate.kotlin.KotlinSyntheticToStringObfuscator;
import proguard.obfuscate.kotlin.KotlinUnsupportedExceptionReplacementSequences;
import proguard.obfuscate.kotlin.KotlinValueParameterNameShrinker;
import proguard.obfuscate.kotlin.KotlinValueParameterUsageMarker;
import proguard.obfuscate.util.InstructionSequenceObfuscator;
import proguard.pass.Pass;
import proguard.resources.file.visitor.ResourceFileProcessingFlagFilter;
import proguard.util.PrintWriterUtil;
import proguard.util.ProcessingFlags;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
/**
* This pass can perform obfuscation of class pools according to a given
* specification.
*
* @author Eric Lafortune
*/
public class Obfuscator implements Pass
{
private static final Logger logger = LogManager.getLogger(Obfuscator.class);
private final Configuration configuration;
public Obfuscator(Configuration configuration)
{
this.configuration = configuration;
}
/**
* Performs obfuscation of the given program class pool.
*/
@Override
public void execute(AppView appView) throws IOException
{
logger.info("Obfuscating...");
// We're using the system's default character encoding for writing to
// the standard output and error output.
PrintWriter out = new PrintWriter(System.out, true);
// Link all non-private, non-static methods in all class hierarchies.
ClassVisitor memberInfoLinker =
new BottomClassFilter(new MethodLinker());
appView.programClassPool.classesAccept(memberInfoLinker);
appView.libraryClassPool.classesAccept(memberInfoLinker);
// If the class member names have to correspond globally,
// additionally link all class members in all program classes.
if (configuration.useUniqueClassMemberNames)
{
appView.programClassPool.classesAccept(new AllMemberVisitor(
new MethodLinker()));
}
// Create a visitor for marking the seeds.
NameMarker nameMarker = new NameMarker();
// All library classes and library class members keep their names.
appView.libraryClassPool.classesAccept(nameMarker);
appView.libraryClassPool.classesAccept(new AllMemberVisitor(nameMarker));
// Mark classes that have the DONT_OBFUSCATE flag set.
appView.programClassPool.classesAccept(
new MultiClassVisitor(
new ClassProcessingFlagFilter(ProcessingFlags.DONT_OBFUSCATE, 0,
nameMarker),
new AllMemberVisitor(
new MemberProcessingFlagFilter(ProcessingFlags.DONT_OBFUSCATE, 0,
nameMarker))));
// We also keep the names of the abstract methods of functional
// interfaces referenced from bootstrap method arguments (additional
// interfaces with LambdaMetafactory.altMetafactory).
// The functional method names have to match the names in the
// dynamic method invocations with LambdaMetafactory.
appView.programClassPool.classesAccept(
new ClassVersionFilter(VersionConstants.CLASS_VERSION_1_7,
new AllAttributeVisitor(
new AttributeNameFilter(Attribute.BOOTSTRAP_METHODS,
new AllBootstrapMethodInfoVisitor(
new AllBootstrapMethodArgumentVisitor(
new ConstantTagFilter(Constant.CLASS,
new ReferencedClassVisitor(
new FunctionalInterfaceFilter(
new ClassHierarchyTraveler(true, false, true, false,
new AllMethodVisitor(
new MemberAccessFilter(AccessConstants.ABSTRACT, 0,
nameMarker))))))))))));
// We also keep the names of the abstract methods of functional
// interfaces that are returned by dynamic method invocations.
// The functional method names have to match the names in the
// dynamic method invocations with LambdaMetafactory.
appView.programClassPool.classesAccept(
new ClassVersionFilter(VersionConstants.CLASS_VERSION_1_7,
new AllConstantVisitor(
new DynamicReturnedClassVisitor(
new FunctionalInterfaceFilter(
new ClassHierarchyTraveler(true, false, true, false,
new AllMethodVisitor(
new MemberAccessFilter(AccessConstants.ABSTRACT, 0,
nameMarker))))))));
if (configuration.keepKotlinMetadata)
{
appView.programClassPool.classesAccept(
// Keep Kotlin default implementations class where the user had already kept the interface.
new ClassProcessingFlagFilter(ProcessingFlags.DONT_OBFUSCATE, 0,
new ReferencedKotlinMetadataVisitor(new KotlinClassToDefaultImplsClassVisitor(nameMarker))));
}
// Mark attributes that have to be kept.
AttributeVisitor attributeUsageMarker =
new NonEmptyAttributeFilter(
new AttributeUsageMarker());
AttributeVisitor optionalAttributeUsageMarker =
configuration.keepAttributes == null ? null :
new AttributeNameFilter(configuration.keepAttributes,
attributeUsageMarker);
appView.programClassPool.classesAccept(
new AllAttributeVisitor(true,
new RequiredAttributeFilter(attributeUsageMarker,
optionalAttributeUsageMarker)));
// Keep parameter names and types if specified.
if (configuration.keepParameterNames)
{
appView.programClassPool.classesAccept(
// Only visits methods that have a name set in their processing info.
// At this step, all methods that have to be kept have been marked
// by the NameMarker with their original name, so this will visit
// only methods that will not be obfuscated.
new AllMethodVisitor(
new NewMemberNameFilter(
new AllAttributeVisitor(true,
new ParameterNameMarker(attributeUsageMarker)))));
if (configuration.keepKotlinMetadata)
{
appView.programClassPool.classesAccept(
new MultiClassVisitor(
// javac and kotlinc don't create the required attributes on interface methods
// so we conservatively mark the parameters as used.
new ClassAccessFilter(AccessConstants.INTERFACE, 0,
new AllMethodVisitor(
new NewMemberNameFilter(
new MethodToKotlinFunctionVisitor(
new AllValueParameterVisitor(
new KotlinValueParameterUsageMarker()))))),
// T14916: Annotation classes don't have underlying JVM constructors,
// so we conservatively mark the parameters as used, if the class is kept.
new ClassAccessFilter(AccessConstants.INTERFACE, 0,
new ClassProcessingFlagFilter(ProcessingFlags.DONT_OBFUSCATE, 0,
new ReferencedKotlinMetadataVisitor(
new KotlinClassKindFilter(metadata -> metadata.flags.isAnnotationClass,
new AllConstructorVisitor(
new AllValueParameterVisitor(
new KotlinValueParameterUsageMarker())))))),
// For all other classes, first check if we should keep
// the parameter names.
new ReferencedKotlinMetadataVisitor(
new KotlinValueParameterUsageMarker())));
}
}
if (configuration.keepKotlinMetadata)
{
appView.programClassPool.classesAccept(
new ReferencedKotlinMetadataVisitor(
new KotlinValueParameterNameShrinker()));
// Keep SourceDebugExtension annotations on Kotlin synthetic classes but obfuscate them.
appView.programClassPool.classesAccept(
new ReferencedKotlinMetadataVisitor(
new KotlinSyntheticClassKindFilter(
KotlinSyntheticClassKindFilter::isLambda,
new KotlinMetadataToClazzVisitor(
new AllAttributeVisitor(
new AttributeNameFilter(Attribute.SOURCE_DEBUG_EXTENSION,
new MultiAttributeVisitor(attributeUsageMarker,
new KotlinSourceDebugExtensionAttributeObfuscator())))))));
}
// Remove the attributes that can be discarded. Note that the attributes
// may only be discarded after the seeds have been marked, since the
// configuration may rely on annotations.
appView.programClassPool.classesAccept(new AttributeShrinker());
if (configuration.keepKotlinMetadata)
{
appView.programClassPool.classesAccept(
new ReferencedKotlinMetadataVisitor(
new KotlinAnnotationFlagFixer()));
}
// Apply the mapping, if one has been specified. The mapping can
// override the names of library classes and of library class members.
if (configuration.applyMapping != null)
{
logger.info("Applying mapping from [{}]...", PrintWriterUtil.fileName(configuration.applyMapping));
WarningPrinter warningPrinter = new WarningLogger(logger, configuration.warn);
MappingReader reader = new MappingReader(configuration.applyMapping);
MappingProcessor keeper =
new MultiMappingProcessor(new MappingProcessor[]
{
new MappingKeeper(appView.programClassPool, warningPrinter),
new MappingKeeper(appView.libraryClassPool, null),
});
reader.pump(keeper);
// Print out a summary of the warnings if necessary.
int warningCount = warningPrinter.getWarningCount();
if (warningCount > 0)
{
logger.warn("Warning: there were {} kept classes and class members that were remapped anyway.",
warningCount);
logger.warn(" You should adapt your configuration or edit the mapping file.");
if (!configuration.ignoreWarnings)
{
logger.warn(" If you are sure this remapping won't hurt,");
logger.warn(" you could try your luck using the '-ignorewarnings' option.");
}
logger.warn(" (https://www.guardsquare.com/proguard/manual/troubleshooting#mappingconflict1)");
if (!configuration.ignoreWarnings)
{
throw new IOException("Please correct the above warnings first.");
}
}
}
// Come up with new names for all classes.
DictionaryNameFactory classNameFactory = configuration.classObfuscationDictionary != null ?
new DictionaryNameFactory(configuration.classObfuscationDictionary, null) :
null;
DictionaryNameFactory packageNameFactory = configuration.packageObfuscationDictionary != null ?
new DictionaryNameFactory(configuration.packageObfuscationDictionary, null) :
null;
appView.programClassPool.classesAccept(
new ClassObfuscator(appView.programClassPool,
appView.libraryClassPool,
classNameFactory,
packageNameFactory,
configuration.useMixedCaseClassNames,
configuration.keepPackageNames,
configuration.flattenPackageHierarchy,
configuration.repackageClasses,
configuration.allowAccessModification,
configuration.keepKotlinMetadata));
if (configuration.keepKotlinMetadata)
{
// Ensure that the companion instance field is named
// the same as the companion class.
appView.programClassPool.classesAccept(
new ReferencedKotlinMetadataVisitor(
new KotlinCompanionEqualizer())
);
}
// Come up with new names for all class members.
NameFactory nameFactory = new SimpleNameFactory();
if (configuration.obfuscationDictionary != null)
{
nameFactory =
new DictionaryNameFactory(configuration.obfuscationDictionary,
nameFactory);
}
WarningPrinter warningPrinter = new WarningLogger(logger, configuration.warn);
// Maintain a map of names to avoid [descriptor - new name - old name].
Map descriptorMap = new HashMap();
// Do the class member names have to be globally unique?
if (configuration.useUniqueClassMemberNames)
{
// Collect all member names in all classes.
appView.programClassPool.classesAccept(
new AllMemberVisitor(
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap)));
// Assign new names to all members in all classes.
appView.programClassPool.classesAccept(
new AllMemberVisitor(
new MemberObfuscator(configuration.overloadAggressively,
nameFactory,
descriptorMap)));
}
else
{
// Come up with new names for all non-private class members.
appView.programClassPool.classesAccept(
new MultiClassVisitor(
// Collect all private member names in this class and down
// the hierarchy.
new ClassHierarchyTraveler(true, false, false, true,
new AllMemberVisitor(
new MemberAccessFilter(AccessConstants.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, AccessConstants.PRIVATE,
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap)))),
// Assign new names to all non-private members in this class.
new AllMemberVisitor(
new MemberAccessFilter(0, AccessConstants.PRIVATE,
new MemberObfuscator(configuration.overloadAggressively,
nameFactory,
descriptorMap))),
// Clear the collected names.
new MapCleaner(descriptorMap)
));
// Come up with new names for all private class members.
appView.programClassPool.classesAccept(
new MultiClassVisitor(
// Collect all member names in this class.
new AllMemberVisitor(
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap)),
// Collect all non-private member names higher up the hierarchy.
new ClassHierarchyTraveler(false, true, true, false,
new AllMemberVisitor(
new MemberAccessFilter(0, AccessConstants.PRIVATE,
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap)))),
// Collect all member names from interfaces of abstract
// classes down the hierarchy.
// Due to an error in the JLS/JVMS, virtual invocations
// may end up at a private method otherwise (Sun/Oracle
// bugs #6691741 and #6684387, ProGuard bug #3471941,
// and ProGuard test #1180).
new ClassHierarchyTraveler(false, false, false, true,
new ClassAccessFilter(AccessConstants.ABSTRACT, 0,
new ClassHierarchyTraveler(false, false, true, false,
new AllMemberVisitor(
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap))))),
// Collect all default method names from interfaces of
// any classes down the hierarchy.
// This is an extended version of the above problem
// (Sun/Oracle bug #802464, ProGuard bug #662, and
// ProGuard test #2060).
new ClassHierarchyTraveler(false, false, false, true,
new ClassHierarchyTraveler(false, false, true, false,
new AllMethodVisitor(
new MemberAccessFilter(0, AccessConstants.ABSTRACT | AccessConstants.STATIC,
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap))))),
// Assign new names to all private members in this class.
new AllMemberVisitor(
new MemberAccessFilter(AccessConstants.PRIVATE, 0,
new MemberObfuscator(configuration.overloadAggressively,
nameFactory,
descriptorMap))),
// Clear the collected names.
new MapCleaner(descriptorMap)
));
}
// Some class members may have ended up with conflicting names.
// Come up with new, globally unique names for them.
NameFactory specialNameFactory =
new SpecialNameFactory(new SimpleNameFactory());
// Collect a map of special names to avoid
// [descriptor - new name - old name].
Map specialDescriptorMap = new HashMap();
appView.programClassPool.classesAccept(
new AllMemberVisitor(
new MemberSpecialNameFilter(
new MemberNameCollector(configuration.overloadAggressively,
specialDescriptorMap))));
appView.libraryClassPool.classesAccept(
new AllMemberVisitor(
new MemberSpecialNameFilter(
new MemberNameCollector(configuration.overloadAggressively,
specialDescriptorMap))));
// Replace conflicting non-private member names with special names.
appView.programClassPool.classesAccept(
new MultiClassVisitor(
// Collect all private member names in this class and down
// the hierarchy.
new ClassHierarchyTraveler(true, false, false, true,
new AllMemberVisitor(
new MemberAccessFilter(AccessConstants.PRIVATE, 0,
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap)))),
// Collect all non-private member names in this class and
// higher up the hierarchy.
new ClassHierarchyTraveler(true, true, true, false,
new AllMemberVisitor(
new MemberAccessFilter(0, AccessConstants.PRIVATE,
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap)))),
// Assign new names to all conflicting non-private members
// in this class and higher up the hierarchy.
new ClassHierarchyTraveler(true, true, true, false,
new AllMemberVisitor(
new MemberAccessFilter(0, AccessConstants.PRIVATE,
new MemberNameConflictFixer(configuration.overloadAggressively,
descriptorMap,
warningPrinter,
new MemberObfuscator(configuration.overloadAggressively,
specialNameFactory,
specialDescriptorMap))))),
// Clear the collected names.
new MapCleaner(descriptorMap)
));
// Replace conflicting private member names with special names.
// This is only possible if those names were kept or mapped.
appView.programClassPool.classesAccept(
new MultiClassVisitor(
// Collect all member names in this class.
new AllMemberVisitor(
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap)),
// Collect all non-private member names higher up the hierarchy.
new ClassHierarchyTraveler(false, true, true, false,
new AllMemberVisitor(
new MemberAccessFilter(0, AccessConstants.PRIVATE,
new MemberNameCollector(configuration.overloadAggressively,
descriptorMap)))),
// Assign new names to all conflicting private members in this
// class.
new AllMemberVisitor(
new MemberAccessFilter(AccessConstants.PRIVATE, 0,
new MemberNameConflictFixer(configuration.overloadAggressively,
descriptorMap,
warningPrinter,
new MemberObfuscator(configuration.overloadAggressively,
specialNameFactory,
specialDescriptorMap)))),
// Clear the collected names.
new MapCleaner(descriptorMap)
));
// Print out any warnings about member name conflicts.
int warningCount = warningPrinter.getWarningCount();
if (warningCount > 0)
{
logger.warn("Warning: there were {} conflicting class member name mappings.", warningCount);
logger.warn(" Your configuration may be inconsistent.");
if (!configuration.ignoreWarnings)
{
logger.warn(" If you are sure the conflicts are harmless,");
logger.warn(" you could try your luck using the '-ignorewarnings' option.");
}
logger.warn(" (https://www.guardsquare.com/proguard/manual/troubleshooting#mappingconflict2)");
if (!configuration.ignoreWarnings)
{
throw new IOException("Please correct the above warnings first.");
}
}
// Obfuscate the Intrinsics.check* method calls.
appView.programClassPool.classesAccept(
new InstructionSequenceObfuscator(
new KotlinIntrinsicsReplacementSequences(appView.programClassPool, appView.libraryClassPool))
);
if (configuration.keepKotlinMetadata)
{
appView.programClassPool.classesAccept(
new MultiClassVisitor(
new ReferencedKotlinMetadataVisitor(
new MultiKotlinMetadataVisitor(
// Come up with new names for Kotlin Properties.
new KotlinPropertyNameObfuscator(nameFactory),
// Obfuscate alias names.
new KotlinAliasNameObfuscator(nameFactory),
// Equalise/fix $DefaultImpls and $WhenMappings classes.
new KotlinSyntheticClassFixer(),
// Ensure object classes have the INSTANCE field.
new KotlinObjectFixer(),
new AllFunctionVisitor(
// Ensure that all default interface implementations of methods have the same names.
new KotlinDefaultImplsMethodNameEqualizer(),
// Ensure all $default methods match their counterpart but with a $default suffix.
new KotlinDefaultMethodNameEqualizer(),
// Obfuscate the throw new UnsupportedOperationExceptions in $default methods
// because they contain the original function name in the string.
new KotlinFunctionToDefaultMethodVisitor(
new InstructionSequenceObfuscator(
new KotlinUnsupportedExceptionReplacementSequences(appView.programClassPool, appView.libraryClassPool)))
),
// Obfuscate toString & toString-impl methods in data classes and inline/value classes.
new KotlinClassKindFilter(
kc -> (kc.flags.isValue || kc.flags.isData),
new KotlinSyntheticToStringObfuscator()))
)
));
appView.resourceFilePool.resourceFilesAccept(
new ResourceFileProcessingFlagFilter(0, ProcessingFlags.DONT_OBFUSCATE,
new KotlinModuleNameObfuscator(nameFactory)));
}
// Print out the mapping, if requested.
if (configuration.printMapping != null)
{
logger.info("Printing mapping to [{}]...", PrintWriterUtil.fileName(configuration.printMapping));
PrintWriter mappingWriter =
PrintWriterUtil.createPrintWriter(configuration.printMapping, out);
try
{
// Print out items that will be renamed.
appView.programClassPool.classesAcceptAlphabetically(
new MappingPrinter(mappingWriter));
}
finally
{
PrintWriterUtil.closePrintWriter(configuration.printMapping,
mappingWriter);
}
}
if (configuration.addConfigurationDebugging)
{
appView.programClassPool.classesAccept(new RenamedFlagSetter());
}
// Collect some statistics about the number of obfuscated
// classes and members.
ClassCounter obfuscatedClassCounter = new ClassCounter();
MemberCounter obfuscatedFieldCounter = new MemberCounter();
MemberCounter obfuscatedMethodCounter = new MemberCounter();
ClassVisitor classRenamer =
new proguard.obfuscate.ClassRenamer(
new ProgramClassFilter(
obfuscatedClassCounter),
new ProgramMemberFilter(
new MethodFilter(
obfuscatedMethodCounter,
obfuscatedFieldCounter))
);
if (configuration.keepKotlinMetadata)
{
// Ensure multi-file parts and facades are in the same package.
appView.programClassPool.classesAccept(
new ReferencedKotlinMetadataVisitor(
new KotlinMultiFileFacadeFixer()));
}
// Actually apply the new names.
appView.programClassPool.classesAccept(classRenamer);
appView.libraryClassPool.classesAccept(classRenamer);
if (configuration.keepKotlinMetadata)
{
// Apply new names to Kotlin properties.
appView.programClassPool.classesAccept(
new ReferencedKotlinMetadataVisitor(
new AllPropertyVisitor(
new KotlinPropertyRenamer())));
}
// Update all references to these new names.
appView.programClassPool.classesAccept(new ClassReferenceFixer(false));
appView.libraryClassPool.classesAccept(new ClassReferenceFixer(false));
appView.programClassPool.classesAccept(new MemberReferenceFixer(configuration.android));
if (configuration.keepKotlinMetadata)
{
appView.programClassPool.classesAccept(
new ReferencedKotlinMetadataVisitor(
new MultiKotlinMetadataVisitor(
new AllTypeVisitor(
// Fix all the alias references.
new KotlinAliasReferenceFixer()),
// Fix all the CallableReference interface methods to match the new names.
new KotlinCallableReferenceFixer(appView.programClassPool, appView.libraryClassPool))));
}
// Make package visible elements public or protected, if obfuscated
// classes are being repackaged aggressively.
if (configuration.repackageClasses != null &&
configuration.allowAccessModification)
{
appView.programClassPool.classesAccept(
new AccessFixer());
// Fix the access flags of the inner classes information.
// Don't change the access flags of inner classes that
// have not been renamed (Guice). [DGD-63]
appView.programClassPool.classesAccept(
new OriginalClassNameFilter(null,
new AllAttributeVisitor(
new AllInnerClassesInfoVisitor(
new InnerClassesAccessFixer()))));
}
// Fix the bridge method flags.
appView.programClassPool.classesAccept(
new AllMethodVisitor(
new BridgeMethodFixer()));
// Rename the source file attributes, if requested.
if (configuration.newSourceFileAttribute != null)
{
appView.programClassPool.classesAccept(new SourceFileRenamer(configuration.newSourceFileAttribute));
}
// Remove unused constants.
appView.programClassPool.classesAccept(
new ConstantPoolShrinker());
logger.info(" Number of obfuscated classes: {}", obfuscatedClassCounter.getCount());
logger.info(" Number of obfuscated fields: {}", obfuscatedFieldCounter.getCount());
logger.info(" Number of obfuscated methods: {}", obfuscatedMethodCounter.getCount());
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy