java-topology/docs/tickets/0004-dependencies-node-list-contains.md
russell@unturf.com db29a08762 undefect. CWE-407 — 92 sites, 42 ecosystems
B&W print-friendly diagrams + tinkerpop-0001 + wave-3 proof sections.
Squash of 94 local commits onto remote master.
2026-03-26 19:48:18 -04:00

1.4 KiB
Raw Permalink Blame History

0004 — Dependencies$GraphDependencies$Node: List.contains() dedup on every addDependency()

Status: open Severity: performance — low-medium Component: jdk.compiler / com.sun.tools.javac.util.Dependencies$GraphDependencies$Node


Root Cause

Dependencies.java:199:

void addDependency(DependencyKind depKind, Node dep) {
    List<Node> deps = depsByKind.get(depKind);
    if (!deps.contains(dep)) {      // O(N) linear scan before every add
        deps.add(dep);
    }
}

deps is a java.util.ArrayList<Node>. The deduplication check scans the entire list on every addDependency() call. Should be a LinkedHashSet (O(1) add with deduplication, preserves insertion order).


Fix

// Replace ArrayList with LinkedHashSet in Node constructor:
EnumMap<CompletionCause, Set<Node>> depsByKind;   // Set, not List

Node(ClassSymbol value) {
    super(value);
    this.depsByKind = new EnumMap<>(CompletionCause.class);
    for (CompletionCause depKind : CompletionCause.values()) {
        depsByKind.put(depKind, new LinkedHashSet<>());    // O(1) add + dedup
    }
}

void addDependency(DependencyKind depKind, Node dep) {
    depsByKind.get(depKind).add(dep);   // dedup is free, no contains() needed
}

Context

GraphDependencies is only active when the debug.completionDeps option is set (disabled by default). Impact is limited to debug/diagnostic compilation runs. Severity lower than 00010003.