Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8336470

Source launcher should work with service loader SPI in unnamed module

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P3 P3
    • 24
    • None
    • tools
    • None
    • In Review
    • 22

      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.
      ```

            cstein Christian Stein
            cstein Christian Stein
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: