On Thu, 18 Jun 2026 08:21:05 GMT, Prasanta Sadhukhan <[email protected]> wrote:
> `DTD.getElement(String)` is not thread safe. If there are 2 parallel parser > threads which call with the same new name then in the Vector there can be 2 > identical elements. These unsynchronized elementHash.get(name) calls can both > observe null before either thread creates and puts the `Element` which will > then have duplicates. The index from elements.size() can also be wrong under > races. > > The block needs to be synchronized to prevent this > > --------- > - [x] I confirm that I make this contribution in accordance with the [OpenJDK > Interim AI Policy](https://openjdk.org/legal/ai). Swing UI classes are generally not thread-safe, yes. But `javax.swing.text.html.parser.DTD` is not really a UI component; it is parser infrastructure with shared mutable caches/maps. If the JDK parser can be reached by parallel parsing code, then this is a real data-race bug: Hashtable/Vector being individually synchronized gives a misleading partial safety, while the compound operation is not atomic Agreed, DTD as a whole is not thread-safe. This change is not intended to make the entire class thread-safe. The reason `getElement(String)` is worth fixing separately is that it performs a compound "lookup or create" operation across two data structures: elementHash and elements. Without synchronization, two concurrent calls for the same new name can create duplicate Element objects and leave the DTD's internal element list inconsistent with the hash table. `DTD.getElement(int) `is different: it indexes into elements and may lazily grow/fill the Vector depending on implementation, so it should be reviewed separately. `DTD.defineEntity` may also have its own races. Those are valid follow-up issues, but they do not make this specific race harmless. But, agreed that fixing only getElement(String) might be incomplete if the intent is to make DTD's lazy lookup/definition paths internally consistent under concurrent parser access so I extend the patch so `getElement(int)`, `getElement(String)`, and `defineEntity ` all synchronize their compound access to the backing DTD tables/vectors and these methods now preserve their internal invariants under concurrent access. ------------- PR Comment: https://git.openjdk.org/jdk/pull/31568#issuecomment-4785605337
