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