Skip to content

Commit

Permalink
fix: resolve JavaNode caching issues (#1775)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Feb 2, 2023
1 parent b1bc5c0 commit 4d00fed
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 37 deletions.
63 changes: 26 additions & 37 deletions jadx-core/src/main/java/jadx/api/JadxDecompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
Expand Down Expand Up @@ -93,10 +92,6 @@ public final class JadxDecompiler implements Closeable {
private BinaryXMLParser binaryXmlParser;
private ProtoXMLParser protoXmlParser;

private final Map<ClassNode, JavaClass> classesMap = new ConcurrentHashMap<>();
private final Map<MethodNode, JavaMethod> methodsMap = new ConcurrentHashMap<>();
private final Map<FieldNode, JavaField> fieldsMap = new ConcurrentHashMap<>();

private final IDecompileScheduler decompileScheduler = new DecompilerScheduler();

private final List<ILoadResult> customLoads = new ArrayList<>();
Expand Down Expand Up @@ -155,10 +150,6 @@ private void reset() {
resources = null;
binaryXmlParser = null;
protoXmlParser = null;

classesMap.clear();
methodsMap.clear();
fieldsMap.clear();
}

@Override
Expand Down Expand Up @@ -471,33 +462,36 @@ synchronized ProtoXMLParser getProtoXmlParser() {
* Get JavaClass by ClassNode without loading and decompilation
*/
@ApiStatus.Internal
JavaClass convertClassNode(ClassNode cls) {
return classesMap.compute(cls, (node, prevJavaCls) -> {
if (prevJavaCls != null && prevJavaCls.getClassNode() == cls) {
// keep previous variable
return prevJavaCls;
}
if (cls.isInner()) {
return new JavaClass(cls, convertClassNode(cls.getParentClass()));
}
return new JavaClass(cls, this);
});
synchronized JavaClass convertClassNode(ClassNode cls) {
JavaClass javaClass = cls.getJavaNode();
if (javaClass == null) {
javaClass = cls.isInner()
? new JavaClass(cls, convertClassNode(cls.getParentClass()))
: new JavaClass(cls, this);
cls.setJavaNode(javaClass);
}
return javaClass;
}

@ApiStatus.Internal
JavaField convertFieldNode(FieldNode field) {
return fieldsMap.computeIfAbsent(field, fldNode -> {
JavaClass parentCls = convertClassNode(fldNode.getParentClass());
return new JavaField(parentCls, fldNode);
});
synchronized JavaField convertFieldNode(FieldNode fld) {
JavaField javaField = fld.getJavaNode();
if (javaField == null) {
JavaClass parentCls = convertClassNode(fld.getParentClass());
javaField = new JavaField(parentCls, fld);
fld.setJavaNode(javaField);
}
return javaField;
}

@ApiStatus.Internal
JavaMethod convertMethodNode(MethodNode method) {
return methodsMap.computeIfAbsent(method, mthNode -> {
ClassNode parentCls = mthNode.getParentClass();
return new JavaMethod(convertClassNode(parentCls), mthNode);
});
synchronized JavaMethod convertMethodNode(MethodNode mth) {
JavaMethod javaMethod = mth.getJavaNode();
if (javaMethod == null) {
javaMethod = new JavaMethod(convertClassNode(mth.getParentClass()), mth);
mth.setJavaNode(javaMethod);
}
return javaMethod;
}

@Nullable
Expand Down Expand Up @@ -574,14 +568,9 @@ public JavaNode getJavaNodeByCodeAnnotation(@Nullable ICodeInfo codeInfo, @Nulla
}
}

@Nullable
private JavaVariable resolveVarNode(VarNode varNode) {
MethodNode mthNode = varNode.getMth();
JavaMethod mth = convertMethodNode(mthNode);
if (mth == null) {
return null;
}
return new JavaVariable(mth, varNode);
JavaMethod javaNode = convertMethodNode(varNode.getMth());
return new JavaVariable(javaNode, varNode);
}

@Nullable
Expand Down
11 changes: 11 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import jadx.api.ICodeInfo;
import jadx.api.ICodeWriter;
import jadx.api.JadxArgs;
import jadx.api.JavaClass;
import jadx.api.impl.SimpleCodeInfo;
import jadx.api.plugins.input.data.IClassData;
import jadx.api.plugins.input.data.IFieldData;
Expand Down Expand Up @@ -100,6 +101,8 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN
// cache maps
private Map<MethodInfo, MethodNode> mthInfoMap = Collections.emptyMap();

private JavaClass javaNode;

public ClassNode(RootNode root, IClassData cls) {
this.root = root;
this.clsInfo = ClassInfo.fromType(root, ArgType.object(cls.getType()));
Expand Down Expand Up @@ -835,6 +838,14 @@ public String getInputFileName() {
return clsData == null ? "synthetic" : clsData.getInputFileName();
}

public JavaClass getJavaNode() {
return javaNode;
}

public void setJavaNode(JavaClass javaNode) {
this.javaNode = javaNode;
}

@Override
public AnnType getAnnType() {
return AnnType.CLASS;
Expand Down
11 changes: 11 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.Collections;
import java.util.List;

import jadx.api.JavaField;
import jadx.api.plugins.input.data.IFieldData;
import jadx.core.dex.attributes.nodes.NotificationAttrNode;
import jadx.core.dex.info.AccessInfo;
Expand All @@ -21,6 +22,8 @@ public class FieldNode extends NotificationAttrNode implements ICodeNode {

private List<MethodNode> useIn = Collections.emptyList();

private JavaField javaNode;

public static FieldNode build(ClassNode cls, IFieldData fieldData) {
FieldInfo fieldInfo = FieldInfo.fromRef(cls.root(), fieldData);
FieldNode fieldNode = new FieldNode(cls, fieldInfo, fieldData.getAccessFlags());
Expand Down Expand Up @@ -112,6 +115,14 @@ public RootNode root() {
return parentClass.root();
}

public JavaField getJavaNode() {
return javaNode;
}

public void setJavaNode(JavaField javaNode) {
this.javaNode = javaNode;
}

@Override
public AnnType getAnnType() {
return AnnType.FIELD;
Expand Down
11 changes: 11 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jadx.api.JavaMethod;
import jadx.api.plugins.input.data.ICodeReader;
import jadx.api.plugins.input.data.IDebugInfo;
import jadx.api.plugins.input.data.IMethodData;
Expand Down Expand Up @@ -71,6 +72,8 @@ public class MethodNode extends NotificationAttrNode implements IMethodDetails,

private List<MethodNode> useIn = Collections.emptyList();

private JavaMethod javaNode;

public static MethodNode build(ClassNode classNode, IMethodData methodData) {
MethodNode methodNode = new MethodNode(classNode, methodData);
methodNode.addAttrs(methodData.getAttributes());
Expand Down Expand Up @@ -610,6 +613,14 @@ public void setUseIn(List<MethodNode> useIn) {
this.useIn = useIn;
}

public JavaMethod getJavaNode() {
return javaNode;
}

public void setJavaNode(JavaMethod javaNode) {
this.javaNode = javaNode;
}

@Override
public AnnType getAnnType() {
return AnnType.METHOD;
Expand Down
4 changes: 4 additions & 0 deletions jadx-gui/src/main/java/jadx/gui/ui/codearea/FridaAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ private List<String> collectMethodArgNames(JavaMethod javaMethod) {
}
return null;
});
int argsCount = javaMethod.getMethodNode().getMethodInfo().getArgsCount();
if (argNames.size() != argsCount) {
LOG.warn("Incorrect args count, expected: {}, got: {}", argsCount, argNames.size());
}
return argNames;
}

Expand Down

0 comments on commit 4d00fed

Please sign in to comment.