Fixed: Proper freeing memory after SWF close

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