Skip to content

JsonProvider should not create a new ServiceLoader for each provider() invocation #26

@glassfishrobot

Description

@glassfishrobot

Affected versions (it's strange, but javax.json.spi.JsonProvider is located both in javax.json:javax.json-api and org.glassfish:javax.json):
javax.json:javax.json-api:1.0 and org.glassfish:javax.json:1.0.4

JsonProvider.provide() is called from Json.createObjectBuilder() and does the following:

public static JsonProvider provider() {
	ServiceLoader<JsonProvider> loader = ServiceLoader.load(JsonProvider.class);
	Iterator<JsonProvider> it = loader.iterator();
	...
}

As you can see it creates a new instance of ServiceLoader (via load(Class) method) each time the method provide() is invoked. Because of this cache of providers maintained by ServiceLoader is not used and loader.iterator() performs heavy search again and again...

The trace looks like

at java.util.zip.ZipFile.getEntry(Native Method)
	at java.util.zip.ZipFile.getEntry(ZipFile.java:311)
	- locked <0x00000000f801b3b8> (a java.util.jar.JarFile)
	at java.util.jar.JarFile.getEntry(JarFile.java:240)
	at java.util.jar.JarFile.getJarEntry(JarFile.java:223)
	at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:841)
	at sun.misc.URLClassPath$JarLoader.findResource(URLClassPath.java:819)
	at sun.misc.URLClassPath$1.next(URLClassPath.java:226)
	at sun.misc.URLClassPath$1.hasMoreElements(URLClassPath.java:236)
	at java.net.URLClassLoader$3$1.run(URLClassLoader.java:589)
	at java.net.URLClassLoader$3$1.run(URLClassLoader.java:587)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader$3.next(URLClassLoader.java:586)
	at java.net.URLClassLoader$3.hasMoreElements(URLClassLoader.java:611)
	at sun.misc.CompoundEnumeration.next(CompoundEnumeration.java:45)
	at sun.misc.CompoundEnumeration.hasMoreElements(CompoundEnumeration.java:54)
	at java.util.ServiceLoader$LazyIterator.hasNextService(ServiceLoader.java:354)
	at java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:393)
	at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:474)
	at javax.json.spi.JsonProvider.provider(JsonProvider.java:89)
	at javax.json.Json.createObjectBuilder(Json.java:266)

In order to solve this performance problem one should create instance of ServiceLoader only once and reuse it in the JsonProvider.provide() method.

Environment

Oracle Java SE Runtime Environment (build 1.8.0-b132)

Affected Versions

[1.0.4]

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions