JDK-8336470 : Source launcher should work with service loader SPI in unnamed module
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 22
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2024-07-16
  • Updated: 2025-05-29
  • Resolved: 2025-05-16
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 25
25 b24Fixed
Related Reports
Blocks :  
Relates :  
Description
Service provider implementations read from a configuration (META-INF/services/TYPE) file fail to work when a Java program is launched in source mode.

The following three-files setup:
- META-INF/services/java.util.spi.ToolProvider
```text
Tool
```

- Main.java
```java
import java.util.ServiceLoader;
import java.util.spi.ToolProvider;

class Main {
  public static void main(String... args) {
    System.out.println(Main.class + " in " + Main.class.getModule());

    System.out.println("1");
    System.out.println(ToolProvider.findFirst("Tool")); // empty due to SCL being used

    System.out.println("2");
    listToolProvidersIn(Main.class.getClassLoader());

    System.out.println("END.");
  }

  static void listToolProvidersIn(ClassLoader loader) {
    try {
      ServiceLoader.load(ToolProvider.class, loader).stream()
          .filter(service -> service.type().getClassLoader() == loader)
          .map(ServiceLoader.Provider::get)
          .forEach(System.out::println);
    } catch (java.util.ServiceConfigurationError error) {
      error.printStackTrace(System.err);
    }
  }
}
```

- Tool.java
```java
import java.io.PrintWriter;
import java.util.spi.ToolProvider;

public record Tool(String name) implements ToolProvider {
  public static void main(String... args) {
    System.exit(new Tool().run(System.out, System.err, args));
  }

  public Tool() {
    this(Tool.class.getName());
  }

  @Override
  public int run(PrintWriter out, PrintWriter err, String... args) {
    out.println(name + "/out");
    err.println(name + "/err");
    return 0;
  }
}
```

yields for running `java Main.java`:

```
class Main in unnamed module @20deea7f
1
Optional.empty
2
END.
```

Note that running `java Tool.java` directly yieds as expected:
```
Tool/out
Tool/err
```

Expected output of `java Main.java`:
```
class Main in unnamed module @2e3967ea
1
Optional.empty
2
Tool[name=Tool]
END.
```
Comments
Changeset: bca293d0 Branch: master Author: Christian Stein <cstein@openjdk.org> Date: 2025-05-16 13:19:01 +0000 URL: https://git.openjdk.org/jdk/commit/bca293d0124af098d36cdfb18c15df18c8ce53b9
16-05-2025

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/20193 Date: 2024-07-16 11:45:47 +0000
16-07-2024