The non-deterministic iteration order of Immutable Collections
Chris Hegarty
chegar999 at gmail.com
Sat Apr 1 10:02:31 UTC 2023
Hi Stuart,
First, thanks for you detailed reply.
On 25/03/2023 00:16, Stuart Marks wrote:
> ...
>
> Yes, this has come up before, but it's been mostly theoretical. That is,
> people worry about this when they hear of the idea of randomized
> iteration order, but I've never heard any followup. This is in fact the
> first time I've heard of an actual case where this is a real problem. So
> thanks for bringing it up.
Here is a link to the GH issue has some more details, and links to
further issues and PR's.
https://github.com/elastic/elasticsearch/issues/94946
> (And unfortunately, it's notoriously difficult to make code truly
> iteration-order dependent. We've had our own history of problems with
> this in the JDK. I'd be interested in hearing from you at some point
> about the exact pathology of how this occurred.)
>
> There's currently no debugging or experimental interface that will let
> one print or set the random seed that's in use. The obvious approach of
> using an agent to hack away at runtime doesn't work, because the
> unmodifiable collections implementations are used very early in startup
> and they're usually loaded before the agent runs. There are limitations
> on what an agent can do when redefining an already-loaded class, for
> example, removing the 'final' modifier from fields isn't supported.
> (Well I suppose one can always use Unsafe.)
Yes, unfortunately that is one of the options that we're considering :-(
> Here's another approach that might work for you.
>
> 1. Write a little program that extracts the class bytes of
> ImmutableCollection.class from the runtime image, and use something like
> ASM or ClassFile to make the class public and to make the REVERSE and
> SALT32L fields public and non-final.
>
> 2. Launch a VM using the --patch-module option to use this class instead
> of the built-in one.
>
> 3. Write an agent, or some debugging library that's called at the right
> time, to use simple reflective access to get or set those fields as
> desired.
>
> This is a bit fiddly but it might be easier than rebuilding and
> deploying a custom JDK.
Yes, certainly a bit fiddly, and maybe a little fragile - we currently
support compiling on JDK 17, with a strong preference of running on the
latest JDK ( currently JDK 20 ). It could be that we'd need to maintain
a version of this for 17 through 20 ( and 21, as we test with EA builds
of 21 ).
> Setting (formerly) final fields after the VM is initialized is often
> somewhat risky. In this case these particular fields are used only
> during iteration, and they don't actually change the layout of any data
> structures. So setting them to some desired value should apply to all
> subsequent iterations, even of existing data structures.
>
> I'll think about better ways to do this in the product. The best
> approach isn't obvious. The typical way of doing things like this using
> system properties is tricky, as it depends on order of class
> initialization at startup (and you know how fragile that is).
Yeah, the set of possible solutions is somewhat curtailed, but "the
simpler the better"! ;-) Something like a system property would be
"good enough", if the initialization order could be enforced.
Thanks,
-Chris.
More information about the core-libs-dev
mailing list