Charset.lookupViaProviders uses new ServiceLoader instance on each miss.

Martin Buchholz martinrb at google.com
Mon Jan 12 19:42:03 UTC 2015


Historical notes:

I added the two-element cache many years ago, assuming that code that
repeatedly accessed more than 2 charsets would be rare.

I have been hoping for a high-quality cache implementation to be added to
the JDK, perhaps via guava, and to use that in places like Charset.

I agree that lookup of non-builtin charsets is heavy-weight.  I don't
recall anyone trying to optimize the lookup itself.  Perhaps you've found
an important opportunity to optimize!


On Mon, Jan 12, 2015 at 11:09 AM, Bernd Eckenfels <ecki at zusammenkunft.net>
wrote:

> 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
>
>



More information about the core-libs-dev mailing list