diff --git a/CHANGELOG.md b/CHANGELOG.md index ef6892cee..2b10c4ec8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file. ### Fixed - [#2456] FLA export - NullPointer exception while exporting to CS4 or lower via commandline - Touch point, snap align and snap to objects incorrect position when editing nested layers +- Proper freeing memory after SWF close ### Fixed - Resize export dialogs labels to match localized strings diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index e64bc8f3e..1c7510e26 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -6239,4 +6239,12 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { public SWF getSwf() { return this; } + + /** + * Checks whether SWF was freed + * @return True if destroyed + */ + public boolean isDestroyed() { + return destroyed; + } } diff --git a/src/com/jpexs/decompiler/flash/easygui/TabSwitcher.java b/src/com/jpexs/decompiler/flash/easygui/TabSwitcher.java index 412d33d6b..3a77da1e4 100644 --- a/src/com/jpexs/decompiler/flash/easygui/TabSwitcher.java +++ b/src/com/jpexs/decompiler/flash/easygui/TabSwitcher.java @@ -24,7 +24,6 @@ import java.awt.event.ComponentEvent; import java.util.ArrayList; import java.util.List; import javax.swing.Icon; -import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.event.ChangeEvent; diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 9740f449a..55dd8ac82 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -1587,6 +1587,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (taskThread != null) { taskThread.interrupt(); + taskThread = null; } if (Configuration._debugMode.get() && swf != null) { @@ -1594,10 +1595,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se Thread t = new Thread() { @Override public void run() { - while (!Thread.currentThread().isInterrupted()) { + while (!Thread.currentThread().isInterrupted()) { DecompilerPool d = fSwf.getDecompilerPool(); statusPanel.setStatus(fSwf.getFileTitle() + " " + d.getStat()); - try { Thread.sleep(100); } catch (InterruptedException ex) { @@ -1620,13 +1620,18 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se isWelcomeScreen = true; quickTagListFindPanel.setVisible(false); quickTreeFindPanel.setVisible(false); - doFilter(); + doFilter(); } mainFrame.setTitle(ApplicationInfo.applicationVerName); mainMenu.updateComponents(null); showView(getCurrentView()); + + if (taskThread != null) { + taskThread.interrupt(); + taskThread = null; + } } private boolean closeConfirmation(OpenableList swfList) { @@ -1774,8 +1779,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } int minEasyIndex = Integer.MAX_VALUE; for (SWF swf : swfsToClose) { - Main.searchResultsStorage.destroySwf(swf); pinsPanel.removeOpenable(swf); + Main.searchResultsStorage.destroySwf(swf); SwfSpecificCustomConfiguration cc = Configuration.getSwfSpecificCustomConfiguration(swf.getShortPathTitle()); if (cc != null) { cc.setCustomData(CustomConfigurationKeys.KEY_LOADED_IMPORT_ASSETS, ""); @@ -1813,14 +1818,18 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se oldItem = null; clear(); - easyPanel.setSwfIndex(minEasyIndex); + Set newSwfs = getAllSwfs(); - SWF newEasySwf = easyPanel.getSwf(); + SWF newEasySwf = null; + if (minEasyIndex < newSwfs.size()) { + easyPanel.setSwfIndex(minEasyIndex); + newEasySwf = easyPanel.getSwf(); + } + + easyPanel.setSwfs(new ArrayList<>(newSwfs)); + easyPanel.setSwf(newEasySwf); if (currentView == VIEW_EASY) { - Set swfs = getAllSwfs(); - easyPanel.setSwfs(new ArrayList<>(swfs)); - easyPanel.setSwf(newEasySwf); updateUi(newEasySwf); } else { updateUi(); diff --git a/src/com/jpexs/decompiler/flash/gui/PinsPanel.java b/src/com/jpexs/decompiler/flash/gui/PinsPanel.java index e75d540ac..e8fcfa3da 100644 --- a/src/com/jpexs/decompiler/flash/gui/PinsPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PinsPanel.java @@ -365,7 +365,14 @@ public class PinsPanel extends JPanel { i--; } } + + if (current != null && current.getOpenable() == openable) { + current = null; + lastSelectedButton = null; + } + save(); + rebuild(); } public void replaceItem(TreeItem oldItem, TreeItem newItem) { diff --git a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeModel.java b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeModel.java index c5a263421..5aec48c7f 100644 --- a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeModel.java +++ b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeModel.java @@ -275,6 +275,7 @@ public class TagListTreeModel extends AbstractTagTreeModel { for (SWF swf : toRemove) { swfHeaders.remove(swf); + removeFromCache(swf); } } diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTreeModel.java b/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTreeModel.java index df8a0229c..684dd9835 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTreeModel.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTreeModel.java @@ -26,9 +26,11 @@ import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.TreeItem; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.WeakHashMap; import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; @@ -48,6 +50,17 @@ public abstract class AbstractTagTreeModel implements TreeModel { protected Map itemToParentCache = new WeakHashMap<>(); + protected void removeFromCache(TreeItem itemToRemove) { + itemToParentCache.remove(itemToRemove); + Set tSet = new HashSet<>(itemToParentCache.keySet()); + for (TreeItem item : tSet) { + TreeItem parent = itemToParentCache.get(item); + if (parent == itemToRemove) { + removeFromCache(item); + } + } + } + public final void calculateCollisions() { Map indices = new WeakHashMap<>(); calculateCollisions(getRoot(), indices); diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java index e37997995..e977feec1 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java @@ -57,6 +57,7 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -146,6 +147,7 @@ public class TagTreeModel extends AbstractTagTreeModel { return AppStrings.translate(key); } + @Override public void updateSwfs(CollectionChangedEvent e) { if (e.getAction() != CollectionChangedAction.ADD && e.getAction() != CollectionChangedAction.MOVE) { @@ -159,6 +161,7 @@ public class TagTreeModel extends AbstractTagTreeModel { for (SWF swf : toRemove) { swfInfos.remove(swf); + removeFromCache(swf); } }