From c04dddfa814176d386604f5473f0ab71c783a0c3 Mon Sep 17 00:00:00 2001 From: Skylot <118523+skylot@users.noreply.github.com> Date: Mon, 16 Jun 2025 17:42:18 +0100 Subject: [PATCH] fix(cli): improve memory usage in jadx-cli (#2524) --- jadx-cli/src/main/java/jadx/cli/JadxCLI.java | 2 ++ .../core/dex/attributes/nodes/JadxCommentsAttr.java | 10 +++++----- .../src/main/java/jadx/core/dex/nodes/ClassNode.java | 2 ++ .../main/java/jadx/core/utils/DecompilerScheduler.java | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLI.java b/jadx-cli/src/main/java/jadx/cli/JadxCLI.java index 7d3a4ab4c..f72a1e98a 100644 --- a/jadx-cli/src/main/java/jadx/cli/JadxCLI.java +++ b/jadx-cli/src/main/java/jadx/cli/JadxCLI.java @@ -11,6 +11,7 @@ import jadx.api.JadxDecompiler; import jadx.api.impl.AnnotatedCodeWriter; import jadx.api.impl.NoOpCodeCache; import jadx.api.impl.SimpleCodeWriter; +import jadx.api.usage.impl.EmptyUsageInfoCache; import jadx.cli.LogHelper.LogLevelEnum; import jadx.cli.plugins.JadxFilesGetter; import jadx.core.utils.exceptions.JadxArgsValidateException; @@ -57,6 +58,7 @@ public class JadxCLI { LogHelper.setLogLevelsForLoadingStage(); JadxArgs jadxArgs = cliArgs.toJadxArgs(); jadxArgs.setCodeCache(new NoOpCodeCache()); + jadxArgs.setUsageInfoCache(new EmptyUsageInfoCache()); jadxArgs.setPluginLoader(new JadxExternalPluginsLoader()); jadxArgs.setFilesGetter(JadxFilesGetter.INSTANCE); initCodeWriterProvider(jadxArgs); diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxCommentsAttr.java b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxCommentsAttr.java index 08894b710..beea5028c 100644 --- a/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxCommentsAttr.java +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxCommentsAttr.java @@ -1,10 +1,11 @@ package jadx.core.dex.attributes.nodes; -import java.util.ArrayList; import java.util.Collections; import java.util.EnumMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import jadx.api.CommentsLevel; @@ -30,10 +31,10 @@ public class JadxCommentsAttr implements IJadxAttribute { return newAttr; } - private final Map> comments = new EnumMap<>(CommentsLevel.class); + private final Map> comments = new EnumMap<>(CommentsLevel.class); public void add(CommentsLevel level, String comment) { - comments.computeIfAbsent(level, l -> new ArrayList<>()).add(comment); + comments.computeIfAbsent(level, l -> new HashSet<>()).add(comment); } public List formatAndFilter(CommentsLevel level) { @@ -47,12 +48,11 @@ public class JadxCommentsAttr implements IJadxAttribute { return e.getValue().stream() .map(v -> "JADX " + levelName + ": " + v); }) - .distinct() .sorted() .collect(Collectors.toList()); } - public Map> getComments() { + public Map> getComments() { return comments; } 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 f337d539c..dd205f3ff 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 @@ -150,6 +150,8 @@ public class ClassNode extends NotificationAttrNode IUsageInfoData usageInfoData = root.getArgs().getUsageInfoCache().get(root); if (usageInfoData != null) { usageInfoData.applyForClass(this); + } else { + LOG.warn("Can't restore usage data for class: {}", this); } } diff --git a/jadx-core/src/main/java/jadx/core/utils/DecompilerScheduler.java b/jadx-core/src/main/java/jadx/core/utils/DecompilerScheduler.java index 7ee9cfa24..44c5462a8 100644 --- a/jadx-core/src/main/java/jadx/core/utils/DecompilerScheduler.java +++ b/jadx-core/src/main/java/jadx/core/utils/DecompilerScheduler.java @@ -65,7 +65,7 @@ public class DecompilerScheduler implements IDecompileScheduler { mergedBatch = new ArrayList<>(MERGED_BATCH_SIZE); } } else { - List batch = new ArrayList<>(depsSize + 1); + List batch = new ArrayList<>(); for (JavaClass dep : cls.getDependencies()) { JavaClass topDep = dep.getTopParentClass(); if (!added.contains(topDep)) { @@ -75,7 +75,7 @@ public class DecompilerScheduler implements IDecompileScheduler { } batch.sort(cmpDepSize); batch.add(cls); - result.add(batch); + result.add(Utils.lockList(batch)); } } if (!mergedBatch.isEmpty()) {