From 3fbcb32b65aea8fc1d4c467699bbe62749b9c1ca Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 25 Apr 2023 15:28:43 -0400 Subject: [PATCH] GP-3352 - Fixed table dispose() exception --- .../FunctionStartRFParamsDialog.java | 10 ++++---- .../widgets/table/AbstractGTableModel.java | 2 +- .../table/threaded/ThreadedTableModel.java | 25 ++++++++++--------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/FunctionStartRFParamsDialog.java b/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/FunctionStartRFParamsDialog.java index e8536b5882..88dc479bed 100644 --- a/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/FunctionStartRFParamsDialog.java +++ b/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/FunctionStartRFParamsDialog.java @@ -162,7 +162,7 @@ public class FunctionStartRFParamsDialog extends ReusableDialogComponentProvider this.plugin = plugin; rowObjects = new ArrayList<>(); trainingSource = plugin.getCurrentProgram(); - JPanel panel = createPanel(); + JPanel panel = createWorkPanel(); addWorkPanel(panel); trainButton = addTrainModelsButton(); addHideDialogButton(); @@ -268,7 +268,7 @@ public class FunctionStartRFParamsDialog extends ReusableDialogComponentProvider return trainModelsButton; } - private JPanel createPanel() { + private JPanel createWorkPanel() { JPanel mainPanel = new JPanel(new BorderLayout()); tableModel = new RandomForestTableModel(plugin.getTool(), rowObjects); @@ -277,7 +277,7 @@ public class FunctionStartRFParamsDialog extends ReusableDialogComponentProvider GTable modelStatsTable = evalPanel.getTable(); modelStatsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); evalPanel.setBorder(BorderFactory.createTitledBorder(MODEL_STATISTICS)); - mainPanel.add(evalPanel, BorderLayout.EAST); + mainPanel.add(evalPanel, BorderLayout.CENTER); DockingAction applyAction = new ActionBuilder(APPLY_MODEL_ACTION_NAME, plugin.getName()) .description("Apply Model to Source Program") @@ -438,7 +438,7 @@ public class FunctionStartRFParamsDialog extends ReusableDialogComponentProvider private JScrollPane getFuncAlignmentScrollPane() { Long modulus = (Long) modBox.getSelectedItem(); int minSize = minimumSizeField.getIntValue(); - //initialize map + //initialize map Map countMap = LongStream.range(0, modulus).boxed().collect(Collectors.toMap(i -> i, i -> 0l)); FunctionIterator fIter = trainingSource.getFunctionManager().getFunctionsNoStubs(true); @@ -514,7 +514,7 @@ public class FunctionStartRFParamsDialog extends ReusableDialogComponentProvider private void searchProgram(Program targetProgram, RandomForestRowObject modelRow) { GetAddressesToClassifyTask getTask = new GetAddressesToClassifyTask(targetProgram, plugin.getMinUndefinedRangeSize()); - //don't want to use the dialog's progress bar + //don't want to use the dialog's progress bar TaskLauncher.launchModal("Gathering Addresses To Classify", getTask); if (getTask.isCancelled()) { return; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/AbstractGTableModel.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/AbstractGTableModel.java index 22b723530e..049fa457d7 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/AbstractGTableModel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/AbstractGTableModel.java @@ -28,7 +28,7 @@ public abstract class AbstractGTableModel extends AbstractTableModel private List lastSelectedObjects = new ArrayList<>(); - private boolean isDisposed; + protected boolean isDisposed; @Override public T getRowObject(int row) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/ThreadedTableModel.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/ThreadedTableModel.java index 20ba674b34..a472d418f3 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/ThreadedTableModel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/ThreadedTableModel.java @@ -162,9 +162,9 @@ public abstract class ThreadedTableModel /** * A package-level method. Subclasses should not call this. - * + * *

This exists to handle whether this model should load incrementally. - * + * * @param monitor the monitor * @return the loaded data * @throws CancelledException if the load was cancelled @@ -221,7 +221,7 @@ public abstract class ThreadedTableModel * This method will retrieve a column value for the given row object. Further, the retrieved * value will be cached. This is useful when sorting a table, as the same column value may * be requested multiple times. - * + * *

Performance Notes *

    *
  • This method uses a {@link HashMap} to cache column values for a row object. Further, @@ -241,7 +241,7 @@ public abstract class ThreadedTableModel * {@link Comparable}. This is possible any time that a row object already has a field * that is used for a given column. *
- * + * * @param rowObject the row object * @param columnIndex the column index for which to get a value * @return the column value @@ -413,7 +413,7 @@ public abstract class ThreadedTableModel * Override this to change how filtering is performed. This implementation will do nothing * if a TableFilter has not been set via a call to * {@link #setTableFilter(TableFilter)}. - * + * * @param data The list of data to be filtered. * @param monitor the progress monitor to check for cancellation. * @param lastSortingContext the comparator used to sort data. This can be used by overridden @@ -513,17 +513,17 @@ public abstract class ThreadedTableModel /** * Removes the specified object from this model and schedules an update. - * + * *

Note: for this method to function correctly, the given object must compare as * {@link #equals(Object)} and have the same {@link #hashCode()} as the object to be removed * from the table data. This allows clients to create proxy objects to pass into this method, * as long as they honor those requirements. - * + * *

If this model's data is sorted, then a binary search will be used to locate the item * to be removed. However, for this to work, all field used to sort the data must still be * available from the original object and must be the same values. If this is not true, then * the binary search will not work and a brute force search will be used. - * + * * @param obj the object to remove */ public void removeObject(ROW_OBJECT obj) { @@ -537,7 +537,7 @@ public abstract class ThreadedTableModel /** * Called when a {@link TableUpdateJob} is cancelled by the user via the Gui. (Disposing of the * table takes a different path.) This is not called when using an incrementally loading - * table model. + * table model. */ protected void backgroundWorkCancelled() { pendingSortContext = null; @@ -668,6 +668,7 @@ public abstract class ThreadedTableModel doClearData(); disposeDynamicColumnData(); clearCache(); + isDisposed = true; } /** @@ -787,7 +788,7 @@ public abstract class ThreadedTableModel /** * Sets the update delay, which is how long the model should wait before updating, after a * change has been made the data. - * + * * @param updateDelayMillis the new update delay. * @param maxUpdateDelayMillis the new max update delay; updates will not wait past this time. */ @@ -818,13 +819,13 @@ public abstract class ThreadedTableModel * Returns the strategy to use for performing adds and removes to this table. Subclasses can * override this method to customize this process for their particular type of data. See the * implementations of {@link TableAddRemoveStrategy} for details. - * + * *

Note: The default add/remove strategy assumes that objects to be removed will be the same * instance that is in the list of this model. This allows the {@link #equals(Object)} and * {@link #hashCode()} to be used when removing the object from the list. If you model does * not pass the same instance into {@link #removeObject(Object)}, then you will need to update * your add/remove strategy accordingly. - * + * * @return the strategy */ protected TableAddRemoveStrategy getAddRemoveStrategy() {