URLStreamHandler.getHostAddress() performance

Mark Sheppard mark.sheppard at oracle.com
Tue Nov 25 14:03:14 UTC 2014


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.rappo at 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.wang at 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
>>>



More information about the security-dev mailing list