GP-1030 - Fixed minor memory leak encountered when using Search -> For Address Tables

Closes #3013
This commit is contained in:
dragonmacher 2021-06-10 18:21:45 -04:00
parent 894ab9515f
commit d119fbac61
12 changed files with 112 additions and 64 deletions

View file

@ -86,9 +86,11 @@ public class CreateStructureDialog extends DialogComponentProvider {
setDefaultButton(okButton);
}
void dispose() {
@Override
public void dispose() {
currentProgram = null;
filterPanel.dispose();
matchingStructuresTable.dispose();
super.dispose();
}
private JPanel buildMainPanel() {

View file

@ -144,9 +144,9 @@ public class AddressTableDialog extends DialogComponentProvider {
// make bottom of right panel
JPanel buttonPanel = new JPanel(new FlowLayout());
buttonPanel.add(makeTablePanel);
buttonPanel.add(disassemblePanel);
JPanel myButtonPanel = new JPanel(new FlowLayout());
myButtonPanel.add(makeTablePanel);
myButtonPanel.add(disassemblePanel);
// search options panel
JPanel searchOptionsPanel = new JPanel(new BorderLayout());
@ -278,7 +278,7 @@ public class AddressTableDialog extends DialogComponentProvider {
offsetPanel.add(viewOffset);
makeOptionsPanel.add(offsetPanel, BorderLayout.NORTH);
makeOptionsPanel.add(buttonPanel, BorderLayout.SOUTH);
makeOptionsPanel.add(myButtonPanel, BorderLayout.SOUTH);
// add panels to left panel
JPanel optionsPanel = new JPanel(new GridLayout(1, 2));
@ -336,8 +336,13 @@ public class AddressTableDialog extends DialogComponentProvider {
@Override
public void close() {
if (!isShowing()) {
return;
}
cancelCurrentTask();
super.close();
resultsTablePanel.dispose();
plugin.dialogDismissed();
}
@ -483,10 +488,6 @@ public class AddressTableDialog extends DialogComponentProvider {
return resultsTable.getSelectedRows();
}
void setModel(AutoTableDisassemblerModel model) {
resultsTablePanel.setModel(model);
}
public void setSelectedRows(int[] selectedRows) {
resultsTable.clearSelection();

View file

@ -16,6 +16,7 @@
package ghidra.app.plugin.core.disassembler;
import java.util.HashMap;
import java.util.Map;
import docking.widgets.table.DiscoverableTableUtils;
import docking.widgets.table.TableColumnDescriptor;
@ -36,12 +37,11 @@ class AutoTableDisassemblerModel extends AddressBasedTableModel<AddressTable> {
private int alignment;
private int skipAmount;
private boolean shiftedAddresses;
private HashMap<Address, AddressTable> map;
private AddressTableStorage storage = new NullStorage();
private AutoTableDisassemblerPlugin plugin;
AutoTableDisassemblerModel(ServiceProvider sp, AutoTableDisassemblerPlugin plugin) {
super(MODEL_NAME, sp, null, TaskMonitor.DUMMY, true);
this.plugin = plugin;
}
@ -60,30 +60,23 @@ class AutoTableDisassemblerModel extends AddressBasedTableModel<AddressTable> {
return descriptor;
}
@Override
public void dispose() {
super.dispose();
storage = new NullStorage();
}
boolean containsKey(Address addr) {
if (map == null) {
return (get(addr) != null);
}
return map.containsKey(addr);
return storage.contains(addr);
}
AddressTable get(Address addr) {
// if map null, then map not initialized, just get it with non-cancelable task monitor
if (map == null) {
return get(addr, TaskMonitor.DUMMY);
}
return map.get(addr);
return storage.get(addr);
}
private AddressTable get(Address addr, TaskMonitor monitor) {
AddressTable entry;
entry = AddressTable.getEntry(getProgram(), addr, monitor, false, minimumTableSize,
return AddressTable.getEntry(getProgram(), addr, monitor, false, minimumTableSize,
alignment, skipAmount, 0, shiftedAddresses, true, false);
if (map != null) {
map.put(addr, entry);
}
return entry;
}
@Override
@ -99,7 +92,7 @@ class AutoTableDisassemblerModel extends AddressBasedTableModel<AddressTable> {
// iterate over addresses in the selected module
AddressIterator addrIter = addresses.getAddresses(true);
map = new HashMap<>();
storage = new MapStorage();
while (addrIter.hasNext()) {
++addrCount;
monitor.checkCanceled();
@ -108,6 +101,7 @@ class AutoTableDisassemblerModel extends AddressBasedTableModel<AddressTable> {
AddressTable tableEntry = get(start, monitor);
if (tableEntry != null) {
storage.put(start, tableEntry);
accumulator.add(tableEntry);
// jump the address iterator by the size of the table entry
@ -142,4 +136,50 @@ class AutoTableDisassemblerModel extends AddressBasedTableModel<AddressTable> {
return table.getNumberAddressEntries();
}
private interface AddressTableStorage {
void put(Address address, AddressTable table);
AddressTable get(Address address);
boolean contains(Address address);
}
private class NullStorage implements AddressTableStorage {
@Override
public void put(Address address, AddressTable table) {
// stub
}
@Override
public AddressTable get(Address address) {
return null; // stub
}
@Override
public boolean contains(Address address) {
return false; // stub
}
}
private class MapStorage implements AddressTableStorage {
private Map<Address, AddressTable> map = new HashMap<>();
@Override
public void put(Address address, AddressTable table) {
map.put(address, table);
}
@Override
public AddressTable get(Address address) {
return map.get(address);
}
@Override
public boolean contains(Address address) {
return map.containsKey(address);
}
}
}

View file

@ -103,6 +103,7 @@ public class AutoTableDisassemblerPlugin extends ProgramPlugin implements Domain
void dialogDismissed() {
addressTableDialog.dispose();
addressTableDialog = null;
if (model != null) {
model.dispose();

View file

@ -102,10 +102,6 @@ public class SetLanguageDialog extends DialogComponentProvider {
return dialogCompilerSpecDescID;
}
void dispose() {
close();
}
@Override
protected void okCallback() {
LanguageCompilerSpecPair selectedLcsPair = selectLangPanel.getSelectedLcsPair();

View file

@ -154,11 +154,6 @@ class MemSearchDialog extends DialogComponentProvider {
updateSearchButtonEnablement();
}
void dispose() {
close();
this.plugin = null;
}
private void setEndianEnabled(boolean enabled) {
littleEndian.setEnabled(enabled);
bigEndian.setEnabled(enabled);

View file

@ -108,11 +108,6 @@ class SearchTextDialog extends DialogComponentProvider {
addDismissButton();
}
void dispose() {
close();
this.plugin = null;
}
@Override
public void close() {
super.close();

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,13 +15,8 @@
*/
package ghidra.app.plugin.core.validator;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.*;
@ -30,6 +24,8 @@ import javax.swing.*;
import docking.DialogComponentProvider;
import docking.widgets.conditiontestpanel.ConditionTestPanel;
import docking.widgets.conditiontestpanel.ConditionTester;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
public class ValidateProgramDialog extends DialogComponentProvider {
private ConditionTestPanel conditionTestPanel;
@ -49,12 +45,7 @@ public class ValidateProgramDialog extends DialogComponentProvider {
runButtonPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
runButtonPanel.setLayout(new FlowLayout());
JButton runTestsButton = new JButton("Run Validators");
runTestsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
conditionTestPanel.runTests();
}
});
runTestsButton.addActionListener(e -> conditionTestPanel.runTests());
runButtonPanel.add(runTestsButton);
mainPanel.add(conditionTestPanel, BorderLayout.CENTER);
mainPanel.add(runButtonPanel, BorderLayout.SOUTH);
@ -69,10 +60,6 @@ public class ValidateProgramDialog extends DialogComponentProvider {
return "Validate: " + program.getDomainFile().getName();
}
void dispose() {
close();
}
@Override
protected void okCallback() {
close();