From c95d64909a882e91fb024dbb52f61c934e033043 Mon Sep 17 00:00:00 2001 From: Skylot Date: Sat, 20 Mar 2021 17:59:02 +0000 Subject: [PATCH] feat(cli): add decompilation progress --- jadx-cli/src/main/java/jadx/cli/JadxCLI.java | 9 ++++++- .../src/main/java/jadx/cli/LogHelper.java | 10 ++++++++ .../main/java/jadx/api/JadxDecompiler.java | 22 ++++++++++++++++ .../src/main/java/jadx/gui/JadxWrapper.java | 25 +++++-------------- 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLI.java b/jadx-cli/src/main/java/jadx/cli/JadxCLI.java index 83880ee4b..4a342d564 100644 --- a/jadx-cli/src/main/java/jadx/cli/JadxCLI.java +++ b/jadx-cli/src/main/java/jadx/cli/JadxCLI.java @@ -42,7 +42,14 @@ public class JadxCLI { jadxArgs.setCodeWriterProvider(SimpleCodeWriter::new); try (JadxDecompiler jadx = new JadxDecompiler(jadxArgs)) { jadx.load(); - jadx.save(); + if (LogHelper.getLogLevel() == LogHelper.LogLevelEnum.QUIET) { + jadx.save(); + } else { + jadx.save(500, (done, total) -> { + int progress = (int) (done * 100.0 / total); + System.out.printf("INFO - progress: %d of %d (%d%%)\r", done, total, progress); + }); + } int errorsCount = jadx.getErrorsCount(); if (errorsCount != 0) { jadx.printErrorsReport(); diff --git a/jadx-cli/src/main/java/jadx/cli/LogHelper.java b/jadx-cli/src/main/java/jadx/cli/LogHelper.java index e92c48841..c84f4b358 100644 --- a/jadx-cli/src/main/java/jadx/cli/LogHelper.java +++ b/jadx-cli/src/main/java/jadx/cli/LogHelper.java @@ -1,5 +1,6 @@ package jadx.cli; +import org.jetbrains.annotations.Nullable; import org.slf4j.LoggerFactory; import com.beust.jcommander.IStringConverter; @@ -31,6 +32,8 @@ public class LogHelper { } } + private static LogLevelEnum logLevelValue; + public static void setLogLevelFromArgs(JadxCLIArgs args) { if (isCustomLogConfig()) { return; @@ -46,6 +49,8 @@ public class LogHelper { } public static void applyLogLevel(LogLevelEnum logLevel) { + logLevelValue = logLevel; + Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); rootLogger.setLevel(logLevel.getLevel()); @@ -56,6 +61,11 @@ public class LogHelper { } } + @Nullable + public static LogLevelEnum getLogLevel() { + return logLevelValue; + } + private static void setLevelForClass(Class cls, Level level) { ((Logger) LoggerFactory.getLogger(cls)).setLevel(level); } diff --git a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java index b0cba377e..6b6dddf69 100644 --- a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java +++ b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java @@ -15,6 +15,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -162,6 +163,27 @@ public final class JadxDecompiler implements Closeable { save(!args.isSkipSources(), !args.isSkipResources()); } + public interface ProgressListener { + void progress(long done, long total); + } + + @SuppressWarnings("BusyWait") + public void save(int intervalInMillis, ProgressListener listener) { + ThreadPoolExecutor ex = (ThreadPoolExecutor) getSaveExecutor(); + ex.shutdown(); + try { + long total = ex.getTaskCount(); + while (ex.isTerminating()) { + long done = ex.getCompletedTaskCount(); + listener.progress(done, total); + Thread.sleep(intervalInMillis); + } + } catch (InterruptedException e) { + LOG.error("Save interrupted", e); + Thread.currentThread().interrupt(); + } + } + public void saveSources() { save(true, false); } diff --git a/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java b/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java index 84f67e849..654bafc09 100644 --- a/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java +++ b/jadx-gui/src/main/java/jadx/gui/JadxWrapper.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.concurrent.ThreadPoolExecutor; import java.util.stream.Collectors; import javax.swing.ProgressMonitor; @@ -66,24 +65,12 @@ public class JadxWrapper { public void saveAll(File dir, ProgressMonitor progressMonitor) { Runnable save = () -> { - try { - decompiler.getArgs().setRootDir(dir); - ThreadPoolExecutor ex = (ThreadPoolExecutor) decompiler.getSaveExecutor(); - ex.shutdown(); - while (ex.isTerminating()) { - long total = ex.getTaskCount(); - long done = ex.getCompletedTaskCount(); - progressMonitor.setProgress((int) (done * 100.0 / total)); - Thread.sleep(500); - } - progressMonitor.close(); - LOG.info("decompilation complete, freeing memory ..."); - decompiler.getClasses().forEach(JavaClass::unload); - LOG.info("done"); - } catch (InterruptedException e) { - LOG.error("Save interrupted", e); - Thread.currentThread().interrupt(); - } + decompiler.getArgs().setRootDir(dir); + decompiler.save(500, (done, total) -> progressMonitor.setProgress((int) (done * 100.0 / total))); + progressMonitor.close(); + LOG.info("decompilation complete, freeing memory ..."); + decompiler.getClasses().forEach(JavaClass::unload); + LOG.info("done"); }; new Thread(save).start(); }