JDK-8213942 : URLStreamHandler initialization race
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 9,11
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2018-11-15
  • Updated: 2019-01-18
  • Resolved: 2018-11-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 12
11.0.2Fixed 12 b21Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
The issue is a timing window in the JDK code (java.net.URL class), it was
introduced sometime after JDK 8 (just diff the URL class source code between
JDK8 and JDK 11 to see the difference there)

 what is happening is that:

   - one thread is setting the factory (URL.setURLStreamHandlerFactory,
     has the lock, and clears the handlers map)
   - another thread simultaneously is in URL.getURLStreamHandler, gets
     to the point where it waits for the lock as the factory is being setup,
when
     it resumes it uses the JDK handler

In the JDK 11 URL.getURLStreamHandler code we see that once it gets the lock
(after the factory was set in the other thread and releases it), if the
handler was null at that point it will get a JDK handler and that will also
end up in the handlers map as well...:

 (the get URL thread is waiting here with a null for handler,
after the set factory thread gives up the lock this proceeds to use the
default handler when it should check if a factory was set to try using that first)

            synchronized (streamHandlerLock) {
                if (handler == null) {
                    // Try the built-in protocol handler
                    handler =defaultFactory.createURLStreamHandler(protocol);
                } else {
                    URLStreamHandler handler2 = null;

This is not an issue in JDK 8 (The JDK 8 code for URL did check for a factory
there after getting the lock...)
Comments
JDK-8064924 changed the behaviour that resulted in this issue.
21-11-2018