diff -r e89c7aaf2906 -r 8595871a5446 src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java --- a/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Fri Aug 30 13:11:16 2019 +0100 +++ b/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Fri Aug 30 15:42:27 2019 +0100 @@ -30,6 +30,8 @@ import java.net.Authenticator.RequestorType; import java.util.Base64; import java.util.HashMap; +import java.util.concurrent.locks.ReentrantLock; + import sun.net.www.HeaderParser; import sun.util.logging.PlatformLogger; import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; @@ -58,6 +60,8 @@ // the cache can be used only once, so after the first use, it's cleaned. static HashMap supported = null; static ThreadLocal > cache = null; + private static final ReentrantLock negotiateLock = new ReentrantLock(); + /* Whether cache is enabled for Negotiate/Kerberos */ private static final boolean cacheSPNEGO; static { @@ -126,40 +130,50 @@ * * @return true if supported */ - private static synchronized boolean isSupportedImpl(HttpCallerInfo hci) { - if (supported == null) { - supported = new HashMap<>(); - } - String hostname = hci.host; - hostname = hostname.toLowerCase(); - if (supported.containsKey(hostname)) { - return supported.get(hostname); - } + private static boolean isSupportedImpl(HttpCallerInfo hci) { + negotiateLock.lock(); + try { + if (supported == null) { + supported = new HashMap<>(); + } + String hostname = hci.host; + hostname = hostname.toLowerCase(); + if (supported.containsKey(hostname)) { + return supported.get(hostname); + } - Negotiator neg = Negotiator.getNegotiator(hci); - if (neg != null) { - supported.put(hostname, true); - // the only place cache.put is called. here we can make sure - // the object is valid and the oneToken inside is not null - if (cache == null) { - cache = new ThreadLocal<>() { - @Override - protected HashMap initialValue() { - return new HashMap<>(); - } - }; + Negotiator neg = Negotiator.getNegotiator(hci); + if (neg != null) { + supported.put(hostname, true); + // the only place cache.put is called. here we can make sure + // the object is valid and the oneToken inside is not null + if (cache == null) { + cache = new ThreadLocal<>() { + @Override + protected HashMap initialValue() { + return new HashMap<>(); + } + }; + } + cache.get().put(hostname, neg); + return true; + } else { + supported.put(hostname, false); + return false; } - cache.get().put(hostname, neg); - return true; - } else { - supported.put(hostname, false); - return false; + } finally { + negotiateLock.unlock(); } } - private static synchronized HashMap getCache() { - if (cache == null) return null; - return cache.get(); + private static HashMap getCache() { + negotiateLock.lock(); + try { + if (cache == null) return null; + return cache.get(); + } finally { + negotiateLock.unlock(); + } } @Override @@ -197,7 +211,7 @@ * @return true if all goes well, false if no headers were set. */ @Override - public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { + public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { try { String response;