Hello, I see some strange scalability problem in an application which uses a few exernal Charsets which are provided by ServiceLoader. When I check the code for Charset.forName()/lookup() I can the 2-entry LRU cache for charsets, and if those caches do not find the charset, it will check standard, extended and loaded charsets.
The later function is here: http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/42770c335bf7/src/java.base/share/classes/java/nio/charset/Charset.java#l341 And it uses ServiceLoader.load() on each lookup. This is unfortunate as it creates a new ServideLoader instance which in turn has its own (empty) service provider cache. So every time a extended charset is loaded (or an unknown charset is requested) it has to parse all the manifests. But what it is even worse, it also has to actually instantiate the found provider (again), so in some cases that provider can also not cache. Do I read the code correct? I think a quick fix would be to hold onto the ServiceLoader. Since it is initialized with the System classloader, there is no need to have a new one on each load. It migh also be worth considerung another 2-level LRU cache inside lookupViaProviders. I am not sure if a reload would be needed for that kind of system serviceloader? Here is a Java7 stacktrace, I think it has'nt changed much in Java9: java.lang.Thread.State: RUNNABLE at sun.misc.ASCIICaseInsensitiveComparator.isUpper(ASCIICaseInsensitiveComparator.java:89) at sun.misc.ASCIICaseInsensitiveComparator.toLower(ASCIICaseInsensitiveComparator.java:93) at sun.misc.ASCIICaseInsensitiveComparator.compare(ASCIICaseInsensitiveComparator.java:48) at sun.misc.ASCIICaseInsensitiveComparator.compare(ASCIICaseInsensitiveComparator.java:36) at java.util.TreeMap.put(TreeMap.java:545) at sun.nio.cs.AbstractCharsetProvider.put(AbstractCharsetProvider.java:84) at sun.nio.cs.AbstractCharsetProvider.charset(AbstractCharsetProvider.java:98) - locked <0x00002b0df808c1e0> (a sun.nio.cs.ext.ExtendedCharsets) at sun.nio.cs.ext.ExtendedCharsets.<init>(ExtendedCharsets.java:349) at sun.reflect.GeneratedConstructorAccessor398.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:526) >>at java.lang.Class.newInstance(Class.java:374) at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:373) at java.util.ServiceLoader$1.next(ServiceLoader.java:445) at java.nio.charset.Charset$1.getNext(Charset.java:357) at java.nio.charset.Charset$1.hasNext(Charset.java:370) at java.nio.charset.Charset$2.run(Charset.java:413) at java.nio.charset.Charset$2.run(Charset.java:411) at java.security.AccessController.doPrivileged(Native Method) >>at java.nio.charset.Charset.lookupViaProviders(Charset.java:410) at java.nio.charset.Charset.lookup2(Charset.java:487) at java.nio.charset.Charset.lookup(Charset.java:475) at java.nio.charset.Charset.isSupported(Charset.java:517) at sun.nio.cs.StreamDecoder.forInputStreamReader(StreamDecoder.java:68) at java.io.InputStreamReader.<init>(InputStreamReader.java:100) In the specific case it also looks like no thread local decoder was used, but I havent looked into that, yet. Gruss Bernd