<html>
  <head>
    <meta content="text/html; charset=windows-1252"
      http-equiv="Content-Type">
  </head>
  <body style="background-color: rgb(255, 255, 255); color: rgb(0, 0,
    0);" text="#000000" bgcolor="#FFFFFF">
    Hi,<br>
    <br>
    Some time ago I dived into the sinchronization pitfalls of URL /
    URLStreamHandler and came up with a possible solution. Here's the
    thread (mostly just my comments) and a patch:<br>
    <br>
    <a class="moz-txt-link-freetext" href="http://mail.openjdk.java.net/pipermail/net-dev/2014-July/008592.html">http://mail.openjdk.java.net/pipermail/net-dev/2014-July/008592.html</a><br>
    <br>
    Regards, Peter<br>
    <br>
    <div class="moz-cite-prefix">On 11/25/2014 03:03 PM, Mark Sheppard
      wrote:<br>
    </div>
    <blockquote cite="mid:54748C22.9030109@oracle.com" type="cite"><!--[if !IE]><DIV style="border-left: 2px solid #009900; border-right: 2px solid #009900;  padding: 0px 15px; margin: 2px 0px;"><![endif]-->I
      think this raises  a more fundamental question, as to why   the
      URL hashCode()  and equals() methods  delegates to
      URLStreamHandler
      <br>
      in the first place? rather than performing the processing within
      the URL class itself, and synchronizing appropriately within.
      <br>
      <br>
      If you call equals() and hasCode() concurrently on the same URL
      instance, there exists the possibility (slight) that
      <br>
      the hostAddress could be set differently, when it is being set for
      the first time, without the synchronization of the
      getHostAddress() in the URLStreamHandler.
      <br>
      <br>
      Although it may rarely happen the mechanics of
      InetAddress.getByName() potentially,  lend itself to a different
      return address
      <br>
      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.
      <br>
      <br>
      regards
      <br>
      Mark
      <br>
      <br>
      On 25/11/2014 12:58, Wang Weijun wrote:
      <br>
      <blockquote type="cite"><!--[if !IE]><DIV style="border-left: 2px solid #009900; border-right: 2px solid #009900;  padding: 0px 15px; margin: 2px 0px;"><![endif]-->
        <blockquote type="cite"><!--[if !IE]><DIV style="border-left: 2px solid #009900; border-right: 2px solid #009900;  padding: 0px 15px; margin: 2px 0px;"><![endif]-->On
          Nov 25, 2014, at 20:25, Pavel Rappo
          <a class="moz-txt-link-rfc2396E" href="mailto:pavel.rappo@oracle.com"><pavel.rappo@oracle.com></a> wrote:
          <br>
          <br>
          Hi Max,
          <br>
          <br>
          I don't see any particular reason for this. Maybe it's just a
          "precaution". It seems to me it's the only field
          <br>
          of the URL class set directly (without setter) from an
          outside.
          <br>
          <br>
          Does it hurt performance a lot? In what cases?
          <br>
          <!--[if !IE]></DIV><![endif]--></blockquote>
        There is a 7x difference in my experiment on
        SecureClassLoader.defineClass().
        <br>
        <br>
        Or, it can be shown using this benchmark:
        <br>
        <br>
        package org.openjdk.bench;
        <br>
        <br>
        import org.openjdk.jmh.annotations.*;
        <br>
        <br>
        import java.io.IOException;
        <br>
        import java.net.URL;
        <br>
        import java.util.*;
        <br>
        import java.util.concurrent.ConcurrentHashMap;
        <br>
        <br>
        @State(Scope.Benchmark)
        <br>
        public class Weird {
        <br>
             final int num = 100;
        <br>
             final Object[] urls = new Object[num];
        <br>
        <br>
             public static class CS {
        <br>
                 private final Object url;
        <br>
                 public CS(Object url) { this.url = url; }
        <br>
                 public int hashCode() { return url.hashCode(); }
        <br>
                 public boolean equals(Object o) { return o instanceof
        CS && url.equals(((CS)o).url); }
        <br>
             }
        <br>
        <br>
             private final Map<Object, Object> pdcacheC = new
        ConcurrentHashMap<>();
        <br>
        <br>
             @Setup
        <br>
             public void init() throws Exception {
        <br>
                 for (int i=0; i< num; i++) {
        <br>
                     urls[i] = new URL(<a class="moz-txt-link-rfc2396E" href="file:/tmp/">"file:/tmp/"</a>+i);
        <br>
                 }
        <br>
             }
        <br>
        <br>
             @State(Scope.Thread)
        <br>
             public static class ThreadState {
        <br>
                 final Random rand = new Random();
        <br>
             }
        <br>
        <br>
        <br>
             @Benchmark
        <br>
             public void setC(ThreadState state) throws IOException {
        <br>
                 Object cs = new CS(urls[next(state)]);
        <br>
                 pdcacheC.computeIfAbsent(cs, x -> "");
        <br>
             }
        <br>
        <br>
             private int next(ThreadState state) {
        <br>
                 return state.rand.nextInt(num);
        <br>
             }
        <br>
        }
        <br>
        <br>
        --Max
        <br>
        <br>
        <br>
        <blockquote type="cite"><!--[if !IE]><DIV style="border-left: 2px solid #009900; border-right: 2px solid #009900;  padding: 0px 15px; margin: 2px 0px;"><![endif]-->-Pavel
          <br>
          <br>
          <blockquote type="cite"><!--[if !IE]><DIV style="border-left: 2px solid #009900; border-right: 2px solid #009900;  padding: 0px 15px; margin: 2px 0px;"><![endif]-->On
            25 Nov 2014, at 12:02, Wang Weijun
            <a class="moz-txt-link-rfc2396E" href="mailto:weijun.wang@oracle.com"><weijun.wang@oracle.com></a> wrote:
            <br>
            <br>
            I am benchmarking security manager and notice this
            <br>
            <br>
            protected synchronized InetAddress getHostAddress(URL u) {
            <br>
               if (u.hostAddress != null)
            <br>
                   return u.hostAddress;
            <br>
            <br>
               String host = u.getHost();
            <br>
               if (host == null || host.equals("")) {
            <br>
                   return null;
            <br>
               } else {
            <br>
                   try {
            <br>
                       u.hostAddress = InetAddress.getByName(host);
            <br>
                   } catch (UnknownHostException ex) {
            <br>
                       return null;
            <br>
                   } catch (SecurityException se) {
            <br>
                       return null;
            <br>
                   }
            <br>
               }
            <br>
               return u.hostAddress;
            <br>
            }
            <br>
            <br>
            Is there any reason why the method is synchronized? Why not
            simply "synchronized (u)"?
            <br>
            <br>
            Thanks
            <br>
            Max
            <br>
            <br>
            <!--[if !IE]></DIV><![endif]--></blockquote>
          <!--[if !IE]></DIV><![endif]--></blockquote>
        <!--[if !IE]></DIV><![endif]--></blockquote>
      <br>
      <!--[if !IE]></DIV><![endif]--></blockquote>
    <br>
  </body>
</html>