I think this raises a more fundamental question, as to why the URL
hashCode() and equals() methods delegates to URLStreamHandler
in the first place? rather than performing the processing within the URL
class itself, and synchronizing appropriately within.
If you call equals() and hasCode() concurrently on the same URL
instance, there exists the possibility (slight) that
the hostAddress could be set differently, when it is being set for the
first time, without the synchronization of the getHostAddress() in the
URLStreamHandler.
Although it may rarely happen the mechanics of InetAddress.getByName()
potentially, lend itself to a different return address
on multiple calls, as it returns the first address from a array of
addresses retrieved - assumption is that the ordering will always be the
same.
regards
Mark
On 25/11/2014 12:58, Wang Weijun wrote:
On Nov 25, 2014, at 20:25, Pavel Rappo <pavel.ra...@oracle.com> wrote:
Hi Max,
I don't see any particular reason for this. Maybe it's just a "precaution". It
seems to me it's the only field
of the URL class set directly (without setter) from an outside.
Does it hurt performance a lot? In what cases?
There is a 7x difference in my experiment on SecureClassLoader.defineClass().
Or, it can be shown using this benchmark:
package org.openjdk.bench;
import org.openjdk.jmh.annotations.*;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@State(Scope.Benchmark)
public class Weird {
final int num = 100;
final Object[] urls = new Object[num];
public static class CS {
private final Object url;
public CS(Object url) { this.url = url; }
public int hashCode() { return url.hashCode(); }
public boolean equals(Object o) { return o instanceof CS &&
url.equals(((CS)o).url); }
}
private final Map<Object, Object> pdcacheC = new ConcurrentHashMap<>();
@Setup
public void init() throws Exception {
for (int i=0; i< num; i++) {
urls[i] = new URL("file:/tmp/"+i);
}
}
@State(Scope.Thread)
public static class ThreadState {
final Random rand = new Random();
}
@Benchmark
public void setC(ThreadState state) throws IOException {
Object cs = new CS(urls[next(state)]);
pdcacheC.computeIfAbsent(cs, x -> "");
}
private int next(ThreadState state) {
return state.rand.nextInt(num);
}
}
--Max
-Pavel
On 25 Nov 2014, at 12:02, Wang Weijun <weijun.w...@oracle.com> wrote:
I am benchmarking security manager and notice this
protected synchronized InetAddress getHostAddress(URL u) {
if (u.hostAddress != null)
return u.hostAddress;
String host = u.getHost();
if (host == null || host.equals("")) {
return null;
} else {
try {
u.hostAddress = InetAddress.getByName(host);
} catch (UnknownHostException ex) {
return null;
} catch (SecurityException se) {
return null;
}
}
return u.hostAddress;
}
Is there any reason why the method is synchronized? Why not simply "synchronized
(u)"?
Thanks
Max