JDK-6460701 : URLClassLoader:addURL RI behavior inconsistent with a spec in case duplicate URLs
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2006-08-16
  • Updated: 2017-05-16
  • Resolved: 2006-12-07
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 7 Other
7 b03Fixed OpenJDK6Fixed
Related Reports
Relates :  
Description
URLClassLoader:addURL RI behavior inconsistent with a spec in case duplicate URLs.

Spec says:

=======spec========
addURL

protected void addURL(URL url)

    Appends the specified URL to the list of URLs to search for classes and resources.

    Parameters:
        url - the URL to be added to the search path of URLs
=====================

But if url already in the list of URLs it will not be appended.
This is so for the latest versions of java6 and java5.

We cannot add URL which already in the list of URLs. However we CAN add duplicate urls providing them at the construction time. But whats the difference if url added in the construction time or later using addURL? Spec says that URL will be appended in any way, so RI should be fixed. However, may be the problem with a spec and spec should say something like "Appends the specified URL to the list of URLs to search for classes and resources, if this URL is not already in the list"


The following sample illustrates the problem.  Sample output follows the code.

=========AddURLBug.java======================
import java.net.URL;
import java.net.MalformedURLException;
import java.net.URLClassLoader;
import java.util.Arrays;


public class AddURLBug {

	private URL url = null;

	private void init()throws MalformedURLException {
		url = new URL("file:///C:/somedir/");
	}

	private void printDebugInformation(URL initialURLs[], URL addedURLs[], URL result[]) {
		System.out.println("INITIAL URLS:");
		for(int i=0; i<initialURLs.length; i++) {
			System.out.println("initialURLs["+i+"] " + initialURLs[i]);
		}
		System.out.println("ADDED URLS:");
		for(int i=0; i<addedURLs.length; i++) {
			System.out.println("addedURLs["+i+"] " + addedURLs[i]);
		}
		System.out.println("RESULT URLS:");
		for(int i=0; i<result.length; i++) {
			System.out.println("result["+i+"] " + result[i]);
		}
	}

	private boolean additionSucceed(Object[] initial, Object[] added, Object[] expected) {
		Object[] result = new Object[initial.length + added.length];
		System.arraycopy(initial, 0, result, 0, initial.length);
		System.arraycopy(added, 0, result, initial.length, added.length);
		return Arrays.equals(expected, result);
	}

	private void addURLs(TestURLClassLoader ucl, URL[] addedURLs) {
		for (int i=0; i<addedURLs.length; i++) {
			ucl.addURLCall(addedURLs[i]);
		}
	}

	private void checkAddURLs(URL[] initial, URL[] added) throws SecurityException {
		TestURLClassLoader ucl = null;

		ucl = new TestURLClassLoader(initial);

		addURLs(ucl, added);
		URL[] resArrayOfURLs = ucl.getURLs();

		if (!additionSucceed(initial, added, resArrayOfURLs)) {
			System.out.println("FAILED");
			printDebugInformation(initial, added, resArrayOfURLs);
		} else {
			System.out.println("PASSED");
			printDebugInformation(initial, added, resArrayOfURLs);
		}
	}

	public static void main(String[] args) throws Exception {
		new AddURLBug().run();
	}
		

	public void run() throws MalformedURLException {
		init();
		URL[] initialURLs = new URL[] {};
		URL[] addedURLs   = new URL[] {url, url, url};
		checkAddURLs(initialURLs, addedURLs);
	}

	private class TestURLClassLoader extends URLClassLoader {

		public TestURLClassLoader(URL[] urls) {
			super(urls);
		}

		public TestURLClassLoader(URL[] urls, ClassLoader parent) {
			super(urls, parent);
		}

		public void addURLCall(URL url) {
			super.addURL(url);
		}
	}

}
========Output1 (build 1.6.0-rc-b95)=========
FAILED
INITIAL URLS:
ADDED URLS:
addedURLs[0] file:/C:/somedir/
addedURLs[1] file:/C:/somedir/
addedURLs[2] file:/C:/somedir/
RESULT URLS:
result[0] file:/C:/somedir/

========Output2 (build 1.5.0_09-ea-b01)========
FAILED
INITIAL URLS:
ADDED URLS:
addedURLs[0] file:/C:/somedir/
addedURLs[1] file:/C:/somedir/
addedURLs[2] file:/C:/somedir/
RESULT URLS:
result[0] file:/C:/somedir/

========Output3 (build 1.5.0-b64)========
PASSED
INITIAL URLS:
ADDED URLS:
addedURLs[0] file:/C:/somedir/
addedURLs[1] file:/C:/somedir/
addedURLs[2] file:/C:/somedir/
RESULT URLS:
result[0] file:/C:/somedir/
result[1] file:/C:/somedir/
result[2] file:/C:/somedir/

========Output4 (build 1.4.2-rc-b25)========
PASSED
INITIAL URLS:
ADDED URLS:
addedURLs[0] file:/C:/somedir/
addedURLs[1] file:/C:/somedir/
addedURLs[2] file:/C:/somedir/
RESULT URLS:
result[0] file:/C:/somedir/
result[1] file:/C:/somedir/
result[2] file:/C:/somedir/

========Output4 (build 1.4.2_11-b06)========
FAILED
INITIAL URLS:
ADDED URLS:
addedURLs[0] file:/C:/somedir/
addedURLs[1] file:/C:/somedir/
addedURLs[2] file:/C:/somedir/
RESULT URLS:
result[0] file:/C:/somedir/

Comments
EVALUATION This change in behavior, addURL not appending duplicate URL's, was as a result of the fix for 5071686. see evaluation section of 5071686: "1. The URL instances grow in number after every reload. URLClassPath has two member fields 'urls'(Stack) and 'path'(ArrayList) and in method addURL(URL url) we are adding the passed 'url' to 'urls' and 'path' without checking if it already exists in them. I modified addURL to avoid the addition if 'url' already exists in the stack and arraylist. With this change the amount of leak decreased." This change should not be an issue for real world applications. The specification for this method should be updated to describe it's new behavior.
16-08-2006