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.
```
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.
```
- relates to
-
JDK-8333131 Source launcher should work with service loader SPI
-
- Resolved
-
- links to
-
Review(master) openjdk/jdk/20193