This is something I wanted to blog about since long time. Although some people had already talked about this beast before, this is not a well known issue, and spreading this information is never enough.
From java.net.URL.equals() javadoc:
Compares this URL for equality with another object.
If the given object is not a URL then this method immediately returns false.
Two URL objects are equal if they have the same protocol, reference equivalent hosts, have the same port number on the host, and the same file and fragment of the file.
Two hosts are considered equivalent if both host names can be resolved into the same IP addresses; else if either host name can’t be resolved, the host names must be equal without regard to case; or both host names equal to null.
Since hosts comparison requires name resolution, this operation is a blocking operation.
Note: The defined behavior for equals is known to be inconsistent with virtual hosting in HTTP.
Now, the java.net.URL.hashCode() javadoc:
Creates an integer suitable for hash table indexing.
The hash code is based upon all the URL components relevant for URL comparison. As such, this operation is a blocking operation.
Note the highlighted phrase. Yes, that’s it… I know exactly what you are thinking…
OMFG!!! java.net.URL.equals() and hashCode() DO A NETWORK CONNECTION!!!
That is one of the biggest traps and horrendous mistakes I’ve seem in JDK code. That is a totally broken example of equals()/hashCode() implementation. An unadvertised developer may be tempted to innocently use URL objects inside some collection and get some headaches…
Actually, that’s what happens in Eclipse update manager (at least until Eclipse 3.3; 3.4 will [hopefully] have a new one). Their code use maps of URL objects as keys to compute update sites from each installed feature. The result is a well known hang in code that was supposed to be very quick:
So, the lesson today is: be very careful with URL objects. NEVER use them as keys in HashMaps or elements in HashSets. NEVER use them in a context where you need to compare them. If possible, work with the String representation of the URL, so you are safe from its evil side effects.