From dcf4a7c4e3eb124cf4548b78ffa6877606b7b1aa Mon Sep 17 00:00:00 2001 From: Skylot Date: Wed, 1 Jun 2022 18:37:58 +0100 Subject: [PATCH] fix(gui): try to resolve some causes of memory leak --- .../src/main/java/jadx/gui/ui/MainWindow.java | 1 + .../src/main/java/jadx/gui/ui/TabbedPane.java | 31 ++++++++++++------- .../java/jadx/gui/ui/dialog/SearchDialog.java | 2 ++ .../src/main/java/jadx/gui/utils/UiUtils.java | 17 ++++++++++ 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java index 29d884cc..7bf189ab 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -437,6 +437,7 @@ public class MainWindow extends JFrame { LogCollector.getInstance().reset(); wrapper.close(); tabbedPane.closeAllTabs(); + UiUtils.resetClipboardOwner(); System.gc(); } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java b/jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java index 7d884045..96585ade 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java @@ -373,49 +373,56 @@ public class TabbedPane extends JTabbedPane { jumps.reset(); curTab = null; lastTab = null; + FocusManager.reset(); } @Nullable public Component getFocusedComp() { - return FocusManager.isActive() ? FocusManager.focusedComp : null; + return FocusManager.getFocusedComp(); } private static class FocusManager implements FocusListener { - static boolean active = false; - static FocusManager listener = new FocusManager(); - static Component focusedComp; + private static final FocusManager INSTANCE = new FocusManager(); + private static @Nullable Component focusedComp; static boolean isActive() { - return active; + return focusedComp != null; + } + + static void reset() { + focusedComp = null; + } + + static Component getFocusedComp() { + return focusedComp; } @Override public void focusGained(FocusEvent e) { - active = true; focusedComp = (Component) e.getSource(); } @Override public void focusLost(FocusEvent e) { - active = false; + focusedComp = null; } static void listen(ContentPanel pane) { if (pane instanceof ClassCodeContentPanel) { - ((ClassCodeContentPanel) pane).getCodeArea().addFocusListener(listener); - ((ClassCodeContentPanel) pane).getSmaliCodeArea().addFocusListener(listener); + ((ClassCodeContentPanel) pane).getCodeArea().addFocusListener(INSTANCE); + ((ClassCodeContentPanel) pane).getSmaliCodeArea().addFocusListener(INSTANCE); return; } if (pane instanceof AbstractCodeContentPanel) { - ((AbstractCodeContentPanel) pane).getCodeArea().addFocusListener(listener); + ((AbstractCodeContentPanel) pane).getCodeArea().addFocusListener(INSTANCE); return; } if (pane instanceof HtmlPanel) { - ((HtmlPanel) pane).getHtmlArea().addFocusListener(listener); + ((HtmlPanel) pane).getHtmlArea().addFocusListener(INSTANCE); return; } if (pane instanceof ImagePanel) { - pane.addFocusListener(listener); + pane.addFocusListener(INSTANCE); return; } // throw new JadxRuntimeException("Add the new ContentPanel to TabbedPane.FocusManager: " + pane); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/dialog/SearchDialog.java b/jadx-gui/src/main/java/jadx/gui/ui/dialog/SearchDialog.java index bb56c471..72b8520f 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/dialog/SearchDialog.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/dialog/SearchDialog.java @@ -147,6 +147,7 @@ public class SearchDialog extends CommonSearchDialog { if (searchDisposable != null && !searchDisposable.isDisposed()) { searchDisposable.dispose(); } + resultsModel.clear(); removeActiveTabListener(); super.dispose(); } @@ -399,6 +400,7 @@ public class SearchDialog extends CommonSearchDialog { if (searchTask != null) { searchTask.cancel(); searchTask.waitTask(); + searchTask = null; } } diff --git a/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java b/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java index 4e03c8cb..cfcad549 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java @@ -329,6 +329,23 @@ public class UiUtils { } } + /** + * Owner field in Clipboard class can store reference to CodeArea. + * This prevents from garbage collection whole jadx object tree and cause memory leak. + * Trying to lost ownership by new empty selection. + */ + public static void resetClipboardOwner() { + try { + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemSelection(); + if (clipboard != null) { + StringSelection selection = new StringSelection(""); + clipboard.setContents(selection, selection); + } + } catch (Exception e) { + LOG.error("Failed to reset clipboard owner", e); + } + } + public static int calcProgress(ITaskProgress taskProgress) { return calcProgress(taskProgress.progress(), taskProgress.total()); } -- GitLab