-
Bug
-
Resolution: Fixed
-
P3
-
9, 11
-
b21
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8214186 | 11.0.3-oracle | Sean Coffey | P3 | Resolved | Fixed | master |
JDK-8217140 | 11.0.3 | Sean Coffey | P3 | Resolved | Fixed | master |
JDK-8214378 | 11.0.2 | Sean Coffey | P3 | Resolved | Fixed | b05 |
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...)
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...)
- backported by
-
JDK-8214186 URLStreamHandler initialization race
-
- Resolved
-
-
JDK-8214378 URLStreamHandler initialization race
-
- Resolved
-
-
JDK-8217140 URLStreamHandler initialization race
-
- Resolved
-
- relates to
-
JDK-8064924 Update java.net.URL to work with modules
-
- Closed
-
-
JDK-8214295 Populate handlers while holding streamHandlerLock
-
- Closed
-
-
JDK-8217364 Custom URLStreamHandler for jrt or file protocol can override default handler.
-
- Resolved
-
(1 relates to)