diff --git a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java index 0caf7dedbf769f4b3cd39a9c72a90bb1eb231fe6..d7f903b8861e544697c67cd97c5b51823f2dc1e2 100644 --- a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java +++ b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java @@ -12,7 +12,6 @@ import java.util.List; 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; @@ -93,10 +92,6 @@ public final class JadxDecompiler implements Closeable { private BinaryXMLParser binaryXmlParser; private ProtoXMLParser protoXmlParser; - private final Map classesMap = new ConcurrentHashMap<>(); - private final Map methodsMap = new ConcurrentHashMap<>(); - private final Map fieldsMap = new ConcurrentHashMap<>(); - private final IDecompileScheduler decompileScheduler = new DecompilerScheduler(); private final List customLoads = new ArrayList<>(); @@ -155,10 +150,6 @@ public final class JadxDecompiler implements Closeable { resources = null; binaryXmlParser = null; protoXmlParser = null; - - classesMap.clear(); - methodsMap.clear(); - fieldsMap.clear(); } @Override @@ -471,33 +462,36 @@ public final class JadxDecompiler implements Closeable { * 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 @@ -574,14 +568,9 @@ public final class JadxDecompiler implements Closeable { } } - @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 diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java index c0465e96e6bbba07079c041fc8bc68398e347a1e..6a981ddeabacfe0463ba58961937e60f1b4e2eb5 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java @@ -21,6 +21,7 @@ import jadx.api.ICodeCache; 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; @@ -100,6 +101,8 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN // cache maps private Map mthInfoMap = Collections.emptyMap(); + private JavaClass javaNode; + public ClassNode(RootNode root, IClassData cls) { this.root = root; this.clsInfo = ClassInfo.fromType(root, ArgType.object(cls.getType())); @@ -835,6 +838,14 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN 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; diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java index bb877c760d66d1cf9d7b73d8bbd6f208c0408d46..be106befd4188ae19a4b7fa0be37765cb396c94f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java @@ -3,6 +3,7 @@ package jadx.core.dex.nodes; 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; @@ -21,6 +22,8 @@ public class FieldNode extends NotificationAttrNode implements ICodeNode { private List 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()); @@ -112,6 +115,14 @@ public class FieldNode extends NotificationAttrNode implements ICodeNode { return parentClass.root(); } + public JavaField getJavaNode() { + return javaNode; + } + + public void setJavaNode(JavaField javaNode) { + this.javaNode = javaNode; + } + @Override public AnnType getAnnType() { return AnnType.FIELD; diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java index 5cd90d1a59652e50af5145d1e254c33930880d99..0512dd464ddbec0e520f6c5f102e9c9bbf215b1b 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable; 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; @@ -71,6 +72,8 @@ public class MethodNode extends NotificationAttrNode implements IMethodDetails, private List useIn = Collections.emptyList(); + private JavaMethod javaNode; + public static MethodNode build(ClassNode classNode, IMethodData methodData) { MethodNode methodNode = new MethodNode(classNode, methodData); methodNode.addAttrs(methodData.getAttributes()); @@ -610,6 +613,14 @@ public class MethodNode extends NotificationAttrNode implements IMethodDetails, this.useIn = useIn; } + public JavaMethod getJavaNode() { + return javaNode; + } + + public void setJavaNode(JavaMethod javaNode) { + this.javaNode = javaNode; + } + @Override public AnnType getAnnType() { return AnnType.METHOD; diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/FridaAction.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/FridaAction.java index 111994f8086d8956fc6f4e80c6d1e0677fcb184d..8658687d97bcff6a8435ae3370a7d17bf931b1c4 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/FridaAction.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/FridaAction.java @@ -141,6 +141,10 @@ public final class FridaAction extends JNodeAction { } return null; }); + int argsCount = javaMethod.getMethodNode().getMethodInfo().getArgsCount(); + if (argNames.size() != argsCount) { + LOG.warn("Incorrect args count, expected: {}, got: {}", argsCount, argNames.size()); + } return argNames; }