diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java
index 0fa93e57b0..6c817cb453 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java
@@ -195,6 +195,11 @@ public class DataTypeArchiveDB extends DomainObjectAdapterDB
}
+ @Override
+ protected void close() {
+ dataTypeManager.dispose();
+ }
+
@Override
protected void setDomainFile(DomainFile df) {
super.setDomainFile(df);
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ManagerDB.java
index fbae0a171e..65b47f389f 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ManagerDB.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ManagerDB.java
@@ -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,13 @@
*/
package ghidra.program.database;
+import java.io.IOException;
+
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOverflowException;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
-import java.io.IOException;
-
/**
* Interface that all subsection managers of a program must implement.
*/
@@ -65,7 +64,7 @@ public interface ManagerDB {
* @param monitor the task monitor to use in any upgrade operations.
* @throws CancelledException if the user cancelled the operation via the task monitor.
*/
- public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor)
+ void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor)
throws CancelledException;
/**
@@ -79,4 +78,12 @@ public interface ManagerDB {
*/
void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
throws AddressOverflowException, CancelledException;
+
+ /**
+ * Callback from the program after being closed to signal this manager to release memory and resources.
+ *
+ */
+ default void dispose() {
+ // default do nothing
+ }
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java
index d38fa24f97..d6976be8ee 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java
@@ -2333,6 +2333,9 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
super.close();
intRangePropertyMap.clear();
addrSetPropertyMap.clear();
+ for (ManagerDB manager : managers) {
+ manager.dispose();
+ }
}
@Override
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java
index 52a3fe12cf..f983f40dc6 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java
@@ -2915,6 +2915,16 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
return (new ArrayList()).iterator();
}
+ public void dispose() {
+ sortedDataTypes = null;
+ enumValueMap = null;
+ }
+
+ @Override
+ public void close() {
+ dispose();
+ }
+
/**
* Invalidates the cache.
*/
@@ -3875,7 +3885,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
for (DataTypeComponent m : c.getDefinedComponents()) {
CompositeDB refC = getCompositeBaseType(m.getDataType());
if (refC != null) {
- graph.addEdge(new DefaultGEdge(c, refC));
+ graph.addEdge(new DefaultGEdge<>(c, refC));
}
}
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java
index 34c33261bf..3732d38535 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java
@@ -253,6 +253,7 @@ public class ProgramDataTypeManager extends DataTypeManagerDB
@Override
public void close() {
// do nothing - cannot close the program's data type manager
+ // dispose should be invoked by the owner of the instance
}
@Override
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProjectDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProjectDataTypeManager.java
index bf3e6767a2..009b565cba 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProjectDataTypeManager.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProjectDataTypeManager.java
@@ -196,9 +196,6 @@ public class ProjectDataTypeManager extends DataTypeManagerDB
// TODO
}
- /**
- * @see ghidra.program.model.data.DataTypeManager#startTransaction(java.lang.String)
- */
@Override
public int startTransaction(String description) {
return dataTypeArchive.startTransaction(description);
@@ -209,26 +206,11 @@ public class ProjectDataTypeManager extends DataTypeManagerDB
dataTypeArchive.flushEvents();
}
- /**
- * @see ghidra.program.model.data.DataTypeManager#endTransaction(int, boolean)
- */
@Override
public void endTransaction(int transactionID, boolean commit) {
dataTypeArchive.endTransaction(transactionID, commit);
-
}
- /**
- * @see ghidra.program.model.data.DataTypeManager#close()
- */
- @Override
- public void close() {
- // do nothing
- }
-
- /* (non-Javadoc)
- * @see ghidra.program.model.data.DomainFileBasedDataTypeManager#getDomainFile()
- */
@Override
public DomainFile getDomainFile() {
return dataTypeArchive.getDomainFile();
@@ -257,4 +239,10 @@ public class ProjectDataTypeManager extends DataTypeManagerDB
}
}
+ @Override
+ public void close() {
+ // do nothing - cannot close a project data type manager
+ // dispose should be invoked by the owner of the instance
+ }
+
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BuiltInDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BuiltInDataTypeManager.java
index f7a59f24c7..c5a3a6e721 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BuiltInDataTypeManager.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BuiltInDataTypeManager.java
@@ -46,12 +46,12 @@ public class BuiltInDataTypeManager extends StandAloneDataTypeManager {
public static synchronized BuiltInDataTypeManager getDataTypeManager() {
if (manager == null) {
manager = new BuiltInDataTypeManager();
- Runnable cleanupTask = new Thread((Runnable) () -> {
+ Runnable cleanupTask = () -> {
if (manager != null) {
- manager.dispose();
+ manager.closeStaticInstance();
manager = null;
}
- }, "Builtin DataType Manager Cleanup Thread");
+ };
ShutdownHookRegistry.addShutdownHook(cleanupTask,
ShutdownPriority.DISPOSE_DATABASES.before());
}
@@ -92,19 +92,11 @@ public class BuiltInDataTypeManager extends StandAloneDataTypeManager {
return super.createCategory(path);
}
- private synchronized void dispose() {
+ private synchronized void closeStaticInstance() {
ClassSearcher.removeChangeListener(classSearcherListener);
super.close();
}
- /* (non-Javadoc)
- * @see ghidra.program.model.data.DataTypeManager#close()
- */
- @Override
- public void close() {
- // static shared instance can't be closed
- }
-
/**
* Refresh the list of Built-In data types found by searching the class path.
*/
@@ -202,4 +194,10 @@ public class BuiltInDataTypeManager extends StandAloneDataTypeManager {
boolean updateCategoryPath) throws DataTypeDependencyException {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public void close() {
+ // do nothing - cannot close a built-in data type manager
+ // close performed automatically during shutdown
+ }
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/FileDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/FileDataTypeManager.java
index 80aa02855e..f735d8b10f 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/FileDataTypeManager.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/FileDataTypeManager.java
@@ -227,11 +227,11 @@ public class FileDataTypeManager extends StandAloneDataTypeManager
@Override
public void close() {
- super.close();
if (packedDB != null) {
packedDB.dispose();
packedDB = null;
}
+ super.close();
}
public boolean isClosed() {
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StandAloneDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StandAloneDataTypeManager.java
index 461f3102fc..8ee2d330aa 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StandAloneDataTypeManager.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StandAloneDataTypeManager.java
@@ -120,6 +120,7 @@ public class StandAloneDataTypeManager extends DataTypeManagerDB {
dbHandle.close();
dbHandle = null;
}
+ super.close();
}
@Override