JDK-8055854 : Examine overhead in java.net.URLClassLoader
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 9
  • Priority: P3
  • Status: Closed
  • Resolution: Won't Fix
  • Submitted: 2014-08-24
  • Updated: 2016-05-09
  • Resolved: 2016-05-09
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Brian Goetz says "I was peeking through the URLClassLoader code, and it seems awfully inefficient.  If we're so concerned about startup, have we evaluated whether that's a part of the problem? e.g., uses exceptions for control flow, doesn't build maps of what is in each JAR, etc"

Synchronization in URLClassLoader is also extremely coarse grained. Low hanging fruit?

This might be helpful when we are attacking the various warmup problems that stem from the huge amounts of classes being generated by Indy.

I know Claes was looking at stuff like this, so I am assigning it to him.

Comments
A large number of improvements and changes have been made as part of the jigsaw integration, e.g., since module-aware classloaders can avoid parent delegation applications can now avoid the exceptional control flow. There are of course room for improvement and micro-optimizations, but time to load classes from the classpath is now dominated by class verification, so any improvement to URLClassPath is likely to have a very limited impact.
09-05-2016

While not eliminating exceptional control flow entirely, the patch pushed as 8057936 mitigates some overhead and show significant startup benefit in real world applications.
18-09-2014

@Claes: Right, these are the sort of things that could easily be done. First question is, though: is this a bottleneck? It seems like it might be, but we should gather data.
26-08-2014

Some good ideas here already, cool. I might add: - The mechanisms to enable laziness could probably be fine-tuned in-place at low risk (replace Stack with ArrayDeque for starters). - Looks to me that many methods are synchronized simply to force visibility when a thread updates boolean closed to true; dropping synchronized and making the boolean volatile might be semantically equivalent but slightly more efficient (dropping synchronized from a method is not altering the public contract, right?) Perhaps suggest micro-optimizing safely (if it gives measurable gains) for 8u and re-evaluate the old startup optimizations in 9 given the impact jigsaw might have on the viability of these old optimizations.
26-08-2014

A few things I noticed just by inspection: - Use of exceptions for control flow. This means that every class found in element N of the classpath will throw N-1 exceptions before getting there. - There's a complex mechanism using synchronization so that we can build the list of loaders lazily (which was almost certainly a startup optimization.) But then we pay a penalty on every subsequent load, effectively paying the cost of having a mutable class path when it is not really mutable. - Could be using more indexing to determine, say, that there's no chance a given path element will satisfy a request for package P, so don't bother asking it.
24-08-2014

There is already work in progress in Jigsaw to use local package maps that will avoid delegation for types that are known to be defined by the extension and boot loaders, this should reduce some of the needing CNF issues. It will also help that the underlying storage for the JDK classes will not be JAR/zip.
24-08-2014

If there is low hanging fruit here and it could be fixed for 8u40, it would be wonderful. Please investigate JDK-8053904 as well, with the given reproducer to see if Nashorns ultra-heavy class installation (due to indy callsites and code regeneration) is affected by any tweaks to this.
24-08-2014