Index: modules/luni/src/main/java/java/net/URLClassLoader.java =================================================================== --- modules/luni/src/main/java/java/net/URLClassLoader.java (revision 507933) +++ modules/luni/src/main/java/java/net/URLClassLoader.java (working copy) @@ -31,6 +31,7 @@ import java.security.SecureClassLoader; import java.security.cert.Certificate; import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; @@ -38,6 +39,7 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.ListIterator; +import java.util.Map; import java.util.StringTokenizer; import java.util.Vector; import java.util.jar.Attributes; @@ -68,8 +70,8 @@ HashSet invalidUrls = new HashSet(); - private IdentityHashMap resCache = new IdentityHashMap( - 32); + private Map resCache = + Collections.synchronizedMap(new IdentityHashMap(32)); private URLStreamHandlerFactory factory; @@ -170,7 +172,9 @@ URL search = createSearchURL(url); urls = addURL(urls, search); orgUrls = addURL(orgUrls, url); - extensions.put(search, null); + synchronized (extensions) { + extensions.put(search, null); + } } catch (MalformedURLException e) { } } @@ -705,23 +709,32 @@ if (protocol.equals("jar")) { //$NON-NLS-1$ jf = resCache.get(currentUrl); if (jf == null) { - /* - * If the connection for currentUrl or resURL is - * used, getJarFile() will throw an exception if the - * entry doesn't exist. - */ - URL jarURL = ((JarURLConnection) currentUrl - .openConnection()).getJarFileURL(); - try { - JarURLConnection juc = (JarURLConnection) new URL( - "jar", "", //$NON-NLS-1$ //$NON-NLS-2$ - jarURL.toExternalForm() + "!/").openConnection(); //$NON-NLS-1$ - jf = juc.getJarFile(); - resCache.put(currentUrl, jf); - } catch (IOException e) { - // Don't look for this jar file again - invalidUrls.add(searchList[i]); - throw e; + // each jf should be found only once + // so we do this job in the synchronized block + synchronized (resCache) { + // Check the cache again in case another thread + // updated it while we're waiting on lock + jf = resCache.get(currentUrl); + if (jf == null) { + /* + * If the connection for currentUrl or resURL is + * used, getJarFile() will throw an exception if the + * entry doesn't exist. + */ + URL jarURL = ((JarURLConnection) currentUrl + .openConnection()).getJarFileURL(); + try { + JarURLConnection juc = (JarURLConnection) new URL( + "jar", "", //$NON-NLS-1$ //$NON-NLS-2$ + jarURL.toExternalForm() + "!/").openConnection(); //$NON-NLS-1$ + jf = juc.getJarFile(); + resCache.put(currentUrl, jf); + } catch (IOException e) { + // Don't look for this jar file again + invalidUrls.add(searchList[i]); + throw e; + } + } } } String entryName; @@ -932,7 +945,12 @@ URL newURL = new URL(protocol, host, port, file + element + "!/"); //$NON-NLS-1$ if (!extensions.containsKey(newURL)) { - extensions.put(newURL, null); + synchronized (extensions) { + if (!extensions.containsKey(newURL)) { + extensions.put(newURL, null); + addedURLs.add(newURL); + } + } addedURLs.add(newURL); } } catch (MalformedURLException e) { @@ -1015,21 +1033,28 @@ if (protocol.equals("jar")) { //$NON-NLS-1$ jf = resCache.get(thisURL); if (jf == null) { - // If the connection for testURL or thisURL is used, - // getJarFile() will throw an exception if the entry - // doesn't exist. - URL jarURL = ((JarURLConnection) thisURL - .openConnection()).getJarFileURL(); - try { - JarURLConnection juc = (JarURLConnection) new URL( - "jar", "", jarURL.toExternalForm() + "!/") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - .openConnection(); - jf = juc.getJarFile(); - resCache.put(thisURL, jf); - } catch (IOException e) { - // Don't look for this jar file again - invalidUrls.add(searchURLs[i]); - throw e; + synchronized (resCache) { + // Check the cache again in case another thread updated it + // updated it while we're waiting on lock + jf = resCache.get(thisURL); + if (jf == null) { + // If the connection for testURL or thisURL is used, + // getJarFile() will throw an exception if the entry + // doesn't exist. + URL jarURL = ((JarURLConnection) thisURL + .openConnection()).getJarFileURL(); + try { + JarURLConnection juc = (JarURLConnection) new URL( + "jar", "", jarURL.toExternalForm() + "!/") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + .openConnection(); + jf = juc.getJarFile(); + resCache.put(thisURL, jf); + } catch (IOException e) { + // Don't look for this jar file again + invalidUrls.add(searchURLs[i]); + throw e; + } + } } } if (thisURL.getFile().endsWith("!/")) { //$NON-NLS-1$