Skip to content

Executable JAR application class encounters performance issues #46063

Closed
@bgoorden

Description

@bgoorden

This issue is basically the same as I described in this issue: Related issue

First of all, thank you for making a fix so fast. I have tested the fix and it does not fix the performance issue of the jar class loader on windows. I investigated a bit further. So the fix makes sure the dns lookup is not executed when there is a host. However in my applications all my URL's do not have a host filled in JarFileUrlKey. So the URLS that are saved in the cache all look like this:

  • protocol: "nested"
  • host: ""
  • port: -1
  • file: "/C:/work/projects/spring-boot-demo/target/test.jar/!BOOT-INF/lib/spring-boot-3.3.13.jar"
  • ref: "null"

I have tested what code in the equals function makes the class loading so slow. It seems to be the synchronized InetAddress getHostAddress() function in java.net.URL:

synchronized InetAddress getHostAddress() {
        if (hostAddress != null) {
            return hostAddress;
        }

        if (host == null || host.isEmpty()) {
            return null;
        }
        try {
            hostAddress = InetAddress.getByName(host);
        } catch (UnknownHostException | SecurityException ex) {
            return null;
        }
        return hostAddress;
}

So for the cache the hostAddress is always null and the host is empty. So it only passes the 2 statements, enters the second one and returns null. The function is synchronized, but it should not have a big impact on performance in this case.

I ran some tests to check performance on the URL class in windows with OpenJDK 17. If I call the hashCode() function on 10,000 URL objects (without host filled) it takes 470ms. When I override the getHostAddress in the UrlStreamHandler with the following code:

@Override
protected InetAddress getHostAddress(URL u) {
      return getHostAddressSynchronized(u);
}

protected InetAddress getHostAddressSynchronized(URL u) {
     synchronized (u) {
          if (u.getHost() == null || u.getHost().isEmpty()) {
               return null;
          }
          try {
               return InetAddress.getByName(u.getHost());
          } catch (UnknownHostException | SecurityException ex) {
               return null;
          }
     }
}

With this override, it only takes 6ms for 10000 hashCode calls. In a HashMap.putIfAbsent the difference is even larger (5ms vs 1400ms). I don't understand why this function in URL has such a performance impact (only on windows openjdk). I think it might be a bug in openjdk.

Would it be possible to use an URI or a String as the key type in the cache of JarFileUrlKey? In my tests that would fix the performance issues with the jar classloader.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions