RFR: JDK-8199216: Memory leak and quadratic layout time with nested nodes (hbox) and pseudo-class in style sheet

John Hendrikx jhendrikx at openjdk.org
Thu Mar 30 17:19:24 UTC 2023


This fix introduces immutable sets of `PseudoClass` almost everywhere, as they are rarely modified.  These are re-used by caching them in a new class `ImmutablePseudoClassSetsCache`.

In order to make this work, `BitSet` had to be cleaned up.  It made assumptions about the collections it is given (which may no longer always be another `BitSet`).  I also added the appropriate null checks to ensure there weren't any other bugs lurking.

Then there was a severe bug in `toArray` in both the subclasses that implement `BitSet`.

The bug in `toArray` was incorrect use of the variable `index` which was used for both advancing the pointer in the array to be generated, as well as for the index to the correct `long` in the `BitSet`.  This must have resulted in other hard to reproduce problems when dealing with `Set<PseudoClass>` or `Set<StyleClass>` if directly or indirectly calling `toArray` (which is for example used by `List.of` and `Set.of`).

The net result of this change is that there are far fewer `PseudoClassState` objects created; the majority of these are never modified, and the few that are left are where you'd expect to see them modified.

A test with 160 nested HBoxes which were given the hover state shows a 99.99% reduction in `PseudoClassState` instances and a 70% reduction in heap use (220 MB -> 68 MB), see the linked ticket for more details.

Although the test case above was extreme, this change should have positive effects for most applications.

-------------

Commit messages:
 - Remove double call to getIndex
 - Fix null test case
 - Fix null addAll call
 - Introduce immutable variant of PseudoClassState, using it where possible
 - Fix several major bugs in BitSet to make it usable as a generic set
 - Remove references to PseudoClassState (private) in Match (public API)

Changes: https://git.openjdk.org/jfx/pull/1076/files
 Webrev: https://webrevs.openjdk.org/?repo=jfx&pr=1076&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8199216
  Stats: 299 lines in 11 files changed: 187 ins; 47 del; 65 mod
  Patch: https://git.openjdk.org/jfx/pull/1076.diff
  Fetch: git fetch https://git.openjdk.org/jfx.git pull/1076/head:pull/1076

PR: https://git.openjdk.org/jfx/pull/1076


More information about the openjfx-dev mailing list