perf(res): XML decoding speed enhancement (PR #1293)

* chore: XML decoding speed improved for large APKs (finding class references)
* skip attach class node to xml for SimpleCodeWriter (used in jadx-cli)

Co-authored-by: Skylot <skylot@gmail.com>
This commit is contained in:
Jan S
2021-11-29 13:08:54 +01:00
committed by GitHub
parent 0a8192168a
commit 05bdf9daae
2 changed files with 39 additions and 2 deletions
@@ -334,6 +334,15 @@ public class RootNode {
return resolveClass(clsInfo);
}
/**
* Searches for ClassNode by its full name (original or alias name)
*
* Warning: This method has a runtime of O(n) (n = number of classes).
* If you need to call it more than once consider {@link #buildFullAliasClassCache()} instead
*
* @param fullName
* @return
*/
@Nullable
public ClassNode searchClassByFullAlias(String fullName) {
for (ClassNode cls : classes) {
@@ -346,6 +355,24 @@ public class RootNode {
return null;
}
/**
*
* @return
*/
public Map<String, ClassNode> buildFullAliasClassCache() {
Map<String, ClassNode> classNameCache = new HashMap<>(classes.size());
for (ClassNode cls : classes) {
ClassInfo classInfo = cls.getClassInfo();
String fullName = classInfo.getFullName();
String alias = classInfo.getAliasFullName();
classNameCache.put(fullName, cls);
if (alias != null && !fullName.equals(alias)) {
classNameCache.put(alias, cls);
}
}
return classNameCache;
}
public List<ClassNode> searchClassByShortName(String shortName) {
List<ClassNode> list = new ArrayList<>();
for (ClassNode cls : classes) {
@@ -56,6 +56,8 @@ public class BinaryXMLParser extends CommonBinaryParser {
private final RootNode rootNode;
private String appPackageName;
private Map<String, ClassNode> classNameCache;
public BinaryXMLParser(RootNode rootNode) {
this.rootNode = rootNode;
try {
@@ -78,7 +80,9 @@ public class BinaryXMLParser extends CommonBinaryParser {
firstElement = true;
decode();
nsMap = null;
return writer.finish();
ICodeInfo codeInfo = writer.finish();
this.classNameCache = null; // reset class name cache
return codeInfo;
}
private boolean isBinaryXml() throws IOException {
@@ -467,6 +471,9 @@ public class BinaryXMLParser extends CommonBinaryParser {
}
private void attachClassNode(ICodeWriter writer, String attrName, String clsName) {
if (!writer.isMetadataSupported()) {
return;
}
if (clsName == null || !attrName.equals("name")) {
return;
}
@@ -476,7 +483,10 @@ public class BinaryXMLParser extends CommonBinaryParser {
} else {
clsFullName = clsName;
}
ClassNode classNode = rootNode.searchClassByFullAlias(clsFullName);
if (classNameCache == null) {
classNameCache = rootNode.buildFullAliasClassCache();
}
ClassNode classNode = classNameCache.get(clsFullName);
if (classNode != null) {
writer.attachAnnotation(classNode);
}