BackendBench
Coffee

Unravel โ€บ Java concepts โ€บ Language basics

Java language

ServiceLoader and plug-ins

ServiceLoader.load(Plugin.class) finds every implementation of an interface that is registered on the class path, without the calling code naming any of them.

Learn these first

At a glance

Mental model

A power socket standard: the appliance maker only knows the socket shape (interface); any plug that fits and is available in the building can be found and used.

What happens, in order
  1. 1Define an interface, put implementations in separate jars, and list them in META-INF/services/com.acme.Plugin (or provides ..with ... in module-info.java).
  2. 2for (Plugin p : ServiceLoader.load(Plugin.class)) p.run(); instantiates the providers lazily, in the order found
  3. 3JDBC drivers, logging backends (SLF4J 2), and many libraries use it, which is why adding a jar to the class path can silently change behaviour
Remember
Watch out
Forgetting the META-INF/services file in the jarUsing the wrong class loader and finding no providersCatching Exception but not ServiceConfigurationError
Example (highlighted lines explain it)
import java.util.ServiceLoader;public class Plugins {  public interface Plugin { String name(); }  static void listAll() {    for (Plugin p : ServiceLoader.load(Plugin.class)) System.out.println(p.name());  }  static Plugin first() { return ServiceLoader.load(Plugin.class).findFirst().orElseThrow(); }}
  1. line 1 uses ServiceLoader, the core of ServiceLoader and plug-ins
  2. line 5 uses ServiceLoader, the core of ServiceLoader and plug-ins
  3. line 7 uses ServiceLoader, the core of ServiceLoader and plug-ins
Read the full explanation (about 1 min)

ServiceLoader.load(Plugin.class) finds every implementation of an interface that is registered on the class path, without the calling code naming any of them. It is Java's built-in plug-in mechanism.

A mental model

A power socket standard: the appliance maker only knows the socket shape (interface); any plug that fits and is available in the building can be found and used.

How it works

Define an interface, put implementations in separate jars, and list them in META-INF/services/com.acme.Plugin (or provides ... with ... in module-info.java).

for (Plugin p : ServiceLoader.load(Plugin.class)) p.run(); instantiates the providers lazily, in the order found.

JDBC drivers, logging backends (SLF4J 2), and many libraries use it, which is why adding a jar to the class path can silently change behaviour.

Going deeper

It is a good way to decouple a library from its implementations but a bad way to wire an application: the order of providers depends on the class path order, and failures surface late. Dependency injection is usually clearer.

Providers need a public no-argument constructor (or a static provider() method in modules). An exception while loading throws ServiceConfigurationError, an Error, not an Exception.

Under the hood

The loader scans META-INF/services resources of the class loader (or the module graph) and caches providers. Which class loader you pass decides what it can see, which matters in application servers and plug-in systems.

Common mistakes

  • Forgetting the META-INF/services file in the jar.
  • Using the wrong class loader and finding no providers.
  • Catching Exception but not ServiceConfigurationError.

How Unravel recognises it

When you paste code, Unravel looks for these signs of serviceloader and plug-ins. Spotting them yourself is a good habit when you read unfamiliar code:

Part of a learning path

Related concepts

Frequently asked questions

What is ServiceLoader and plug-ins?

ServiceLoader.load(Plugin.class) finds every implementation of an interface that is registered on the class path, without the calling code naming any of them. It is Java's built-in plug-in mechanism.

What are the most common mistakes with ServiceLoader and plug-ins?

Forgetting the META-INF/services file in the jar. Using the wrong class loader and finding no providers. Catching Exception but not ServiceConfigurationError.

How can I see ServiceLoader and plug-ins in real code?

Paste your own Java into Unravel and it will point out where serviceloader and plug-ins appears, explain how it works at the detail level you choose, and draw the flow of the code around it.