package jadx.gui.jobs; import jadx.gui.ui.ProgressPanel; import jadx.gui.utils.CacheObject; import jadx.gui.utils.search.TextSearchIndex; import jadx.gui.utils.Utils; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import java.util.concurrent.Future; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class BackgroundWorker extends SwingWorker<Void, Void> { private static final Logger LOG = LoggerFactory.getLogger(BackgroundWorker.class); private final CacheObject cache; private final ProgressPanel progressPane; public BackgroundWorker(CacheObject cacheObject, ProgressPanel progressPane) { this.cache = cacheObject; this.progressPane = progressPane; } public void exec() { if (isDone()) { return; } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { progressPane.setVisible(true); } }); addPropertyChangeListener(progressPane); execute(); } public void stop() { if (isDone()) { return; } LOG.debug("Canceling background jobs ..."); cancel(false); } @Override protected Void doInBackground() throws Exception { try { System.gc(); LOG.debug("Memory usage: Before decompile: {}", Utils.memoryInfo()); runJob(cache.getDecompileJob()); LOG.debug("Memory usage: Before index: {}", Utils.memoryInfo()); runJob(cache.getIndexJob()); LOG.debug("Memory usage: After index: {}", Utils.memoryInfo()); System.gc(); LOG.debug("Memory usage: After gc: {}", Utils.memoryInfo()); TextSearchIndex searchIndex = cache.getTextIndex(); if (searchIndex != null && searchIndex.getSkippedCount() > 0) { LOG.warn("Indexing of some classes skipped, count: {}, low memory: {}", searchIndex.getSkippedCount(), Utils.memoryInfo()); } } catch (Exception e) { LOG.error("Exception in background worker", e); } return null; } private void runJob(BackgroundJob job) { if (isCancelled()) { return; } progressPane.changeLabel(this, job.getInfoString()); Future<Boolean> future = job.process(); while (!future.isDone()) { try { setProgress(job.getProgress()); if (isCancelled()) { future.cancel(false); } Thread.sleep(500); } catch (Exception e) { LOG.error("Background worker error", e); } } } @Override protected void done() { progressPane.setVisible(false); } }