Summary
AggregateManager has two related problems: a static ArrayList field mutated from unsynchronized public methods, and multiple methods that return ArrayList<Target> rather than the List<Target> interface.
Unsynchronized static mutable field
private static ArrayList<Target> m_ignoreList = new ArrayList<>();
private static String m_location = null;
private static Target m_latestBundle = null;
buildBundleIgnoreList, buildCollectionIgnoreList, and makeException all mutate or read m_ignoreList without synchronization. Concurrent bundle validations calling makeException can interleave addAll operations, causing ConcurrentModificationException or lost updates. m_location and m_latestBundle have unsynchronized read/write.
Live-reference getter
public static ArrayList<Target> getIgnoreList() {
return (AggregateManager.m_ignoreList);
}
Returns the actual backing list — callers can clear or mutate it.
Concrete return types
getIgnoreList(), buildBundleIgnoreList(...), buildCollectionIgnoreList(...), findOtherBundleFiles(...), findOtherCollectionFiles(...), and getCollectionFilesWithSameLogicalIdentifier(...) all return ArrayList<Target> instead of List<Target>.
Recommended fix
- Replace
m_ignoreList with CopyOnWriteArrayList or wrap all accesses with synchronized (AggregateManager.class).
- Use
volatile for m_location and m_latestBundle.
- Change
getIgnoreList() return type to List<Target> and return Collections.unmodifiableList(m_ignoreList).
- Change all other method return types from
ArrayList<Target> to List<Target>.
Related
Identified during immutability/synchronization audit triggered by PR #1607 review feedback.
🤖 Generated with Claude Code
Summary
AggregateManagerhas two related problems: a staticArrayListfield mutated from unsynchronized public methods, and multiple methods that returnArrayList<Target>rather than theList<Target>interface.Unsynchronized static mutable field
buildBundleIgnoreList,buildCollectionIgnoreList, andmakeExceptionall mutate or readm_ignoreListwithout synchronization. Concurrent bundle validations callingmakeExceptioncan interleaveaddAlloperations, causingConcurrentModificationExceptionor lost updates.m_locationandm_latestBundlehave unsynchronized read/write.Live-reference getter
Returns the actual backing list — callers can clear or mutate it.
Concrete return types
getIgnoreList(),buildBundleIgnoreList(...),buildCollectionIgnoreList(...),findOtherBundleFiles(...),findOtherCollectionFiles(...), andgetCollectionFilesWithSameLogicalIdentifier(...)all returnArrayList<Target>instead ofList<Target>.Recommended fix
m_ignoreListwithCopyOnWriteArrayListor wrap all accesses withsynchronized (AggregateManager.class).volatileform_locationandm_latestBundle.getIgnoreList()return type toList<Target>and returnCollections.unmodifiableList(m_ignoreList).ArrayList<Target>toList<Target>.Related
Identified during immutability/synchronization audit triggered by PR #1607 review feedback.
🤖 Generated with Claude Code