That would also be my understanding of the current situation, though this 
contradicts what
Claes wrote.
Maybe the JVM behaves in a way which does not allow reordering, but the JLS 
definitely seems
to allow it. Section § 12.2.4 [0] only mentions that for the class to be 
initialized there
has to exist a lock LC (or at least the happens-before relationship), but there 
is no
"freeze the world" or anything similar which would force a happens-before 
relationship
for the code in `SharedSecrets`.

Maybe most of the `SharedSecrets` methods are thread-safe (albeit extremely 
brittle) because
the classes to which the accessor objects belong to have previously already 
been loaded
before `SharedSecrets` is used, therefore having already established a 
happens-before
relationship.
However, this is definitely not the case for all of the methods as shown by the 
following
example:
```
CookieHandler.setDefault(new CookieHandler() {
    @Override
    public void put(URI uri, Map<String, List<String>> responseHeaders) throws 
IOException { }
    
    @Override
    public Map<String, List<String>> get(URI uri, Map<String, List<String>> 
requestHeaders) throws IOException {
        return Collections.emptyMap();
    }
});

// Any site which uses cookies (i.e. Set-Cookie or Set-Cookie2 header)
URL url = new URL("https://oracle.com";);
url.openConnection().getHeaderFields();
```

Running this code with `openjdk 15 2020-09-15` shows that the call to 
`SharedSecrets.getJavaNetHttpCookieAccess()` is made before the class 
`HttpCookie` has
been accessed and initialized. Therefore merely running this code in two 
separate threads
(both having been started before the code is executed, since `Thread.start()` 
establishes
a happens-before relationship) should be enough to render that `SharedSecrets` 
method
non-thread-safe.

Kind regards


[0] https://docs.oracle.com/javase/specs/jls/se15/html/jls-12.html#jls-12.4.2

> Hans Boehm <hbo...@google.com> hat am 29. Dezember 2020 um 18:53 geschrieben: 
>
> If static_field is not volatile, and set concurrently, then the first read of 
> static_field may return non-null and the second null, without initialize() 
> even being executed. The Java memory model does not prevent reordering of 
> non-volatile reads from the same field (for good reason).
>  
> Even if initialize() is executed and performs a volatile read, this reasoning 
> doesn't hold. The initial static_field read may be delayed past the volatile 
> read inside the conditional and hence, at least theoretically, past the 
> second read. Control dependencies don't order reads, either in Java, or in 
> modern weakly-ordered architectures with branch prediction. This doesn't 
> matter if initialize() sets static_field.
>  
> This all assumes that having two threads call initialize() is OK.
>  
> Java code with data races is extremely tricky and rarely correct.
>  
> Hans

Reply via email to