Java Language ServiceLoader


ServiceLoader can be used to get instances of classes extending a given type(=service) that are specified in a file packed in a .jar file. The service that is extended/implemented is often a interface, but this is not required.

The extending/implementing classes need to provide a zero argument constructor for the ServiceLoader to instantiate them.

To be discovered by the ServiceLoader a text file with the name of the fully qualified type name of the implemented service needs to be stored inside the META-INF/services directory in the jar file. This file contains one fully qualified name of a class implementing the service per line.

Logger Service

The following example shows how to instantiate a class for logging via the ServiceLoader.


package servicetest;


public interface Logger extends AutoCloseable {
    void log(String message) throws IOException;

Implementations of the service

The following implementation simply writes the message to System.err

package servicetest.logger;

import servicetest.Logger;

public class ConsoleLogger implements Logger {

    public void log(String message) {

    public void close() {


The following implementation writes the messages to a text file:

package servicetest.logger;

import servicetest.Logger;

public class FileLogger implements Logger {

    private final BufferedWriter writer;

    public FileLogger() throws IOException {
        writer = new BufferedWriter(new FileWriter("log.txt"));

    public void log(String message) throws IOException {

    public void close() throws IOException {



The META-INF/services/servicetest.Logger file lists the names of the Logger implementations.



The following main method writes a message to all available loggers. The loggers are instantiated using ServiceLoader.

public static void main(String[] args) throws Exception {
    final String message = "Hello World!";

    // get ServiceLoader for Logger
    ServiceLoader<Logger> loader = ServiceLoader.load(servicetest.Logger.class);

    // iterate through instances of available loggers, writing the message to each one
    Iterator<Logger> iterator = loader.iterator();
    while (iterator.hasNext()) {
        try (Logger logger = {

Simple ServiceLoader Example

The ServiceLoader is a simple and easy to use built-in mechanism for dynamic loading of interface implementations. With the service loader - providing means for instantation (but not the wiring) - a simple dependency injection mechanism can be built in Java SE. With the ServiceLoader interface and implementation separation becomes natural and programs can be conveniently extended. Actually a lot of Java API are implented based on the ServiceLoader

The basic concepts are

  • Operating on interfaces of services
  • Obtaining implementation(s) of the service via ServiceLoader
  • Providing implementation of servics

Lets start with the interface and put it in a jar, named for example accounting-api.jar

package example;

public interface AccountingService {

  long getBalance();

Now we provide an implementation of that service in a jar named accounting-impl.jar, containing an implementation of the service

package example.impl;
import example.AccountingService;

public interface DefaultAccountingService implements AccouningService {

  public long getBalance() {
    return balanceFromDB();

  private long balanceFromDB(){

further, the accounting-impl.jar contains a file declaring that this jar provides an implementation of AccountingService. The file has to have a path starting with META-INF/services/ and must have the same name as the fully-qualified name of the interface:

  • META-INF/services/example.AccountingService

The content of the file is the fully-qualfified name of the implementation:


Given both jars are in the classpath of the program, that consumes the AccountingService, an instance of the Service can be obtained by using the ServiceLauncher

ServiceLoader<AccountingService> loader = ServiceLoader.load(AccountingService.class)
AccountingService service =;
long balance = service.getBalance();

As the ServiceLoader is an Iterable, it supports multiple implementation providers, where the program may choose from:

ServiceLoader<AccountingService> loader = ServiceLoader.load(AccountingService.class)
for(AccountingService service : loader) {

Note that when invoking next() a new instance will allways be created. If you want to re-use an instance, you have to use the iterator() method of the ServiceLoader or the for-each loop as shown above.