Re: Proposal: Static Service Traits—Enhancing Java’s Static Polymorphism and ServiceLoader Facilities

Remi Forax forax at univ-mlv.fr
Wed Jan 28 16:59:21 UTC 2026


Hello, 
Alex Buckley has a nice presentation about how to use modules and services. [1] 

And you can then binds the services using jlink. 

regards, 
Rémi 

[1] https://www.youtube.com/watch?v=RjVjm4uuMvc 

> From: "Steffen Yount" <steffenyount at gmail.com>
> To: "amber-dev" <amber-dev at openjdk.org>
> Sent: Wednesday, January 28, 2026 1:28:40 AM
> Subject: Proposal: Static Service Traits—Enhancing Java’s Static Polymorphism
> and ServiceLoader Facilities

> The recent thread "Java Language Enhancement: Disallow access to static members
> via object references" highlights a long-standing tension in Java's handling of
> static members. While that thread seeks to further decouple instance state from
> static logic, I would like to propose moving in the opposite direction:
> "doubling down" on Java’s compile-time and link-time static polymorphism.

> By beefing up java.util.ServiceLoader facilities and integrating its discovery
> mechanism directly into the language via Static Service Traits , we can
> facilitate the "Witness Object" paradigm discussed by Brian Goetz's " growing
> the java language " presentation and the algebraic "well-known interface" model
> for custom numeric types (like Float16 ) proposed in Joe Darcy's " Paths to
> Support Additional Numeric Types on the Java Platform " presentation.

> == Static Service Traits for Java ==

> I propose a system of Static Service Traits . I use the term "Trait" advisedly:
> this feature adopts a rigorous Coherence Model (inspired by systems like Rust)
> to ensure that service resolution is not merely a dynamic search, but a
> type-safe, deterministic binding of static capabilities to types.

> 1. The service Contextual Keyword
> We introduce service as a contextual modifier for interface declarations.
> Marking an interface as a service identifies it as a "service type" with a
> contract for static capabilities and a high-performance service provider
> registry.

> 2. Static Implementations and Extension Methods

>     * Static Implementations:
>        * In Interface Headers: interface MyTrait implements ServiceX<T> . Methods are
>         fulfilled as static .
>        * In Class Headers: class MyClass implements static Numeric<Float16> . Methods
>        are implemented as static on the class. Existing signature rules prevent a
>         method from being both a static and an instance implementation simultaneously.
>    * Static Extension Methods: Desugared at the call site. myInstance.method()
>    becomes MyClass.method(myInstance) . Notably, if myInstance is null , it
>     desugars to MyClass.method(null) without an immediate NullPointerException .
>    * Ergonomic Aliases: To simplify signatures, we introduce private nested static
>     type aliases This and Super (e.g., static This add(This a, This b) ).

> 3. Operational Mechanics & Link-Time Integration
> A ServiceLoader Controller is integrated into the JVM’s class-loading pipeline.
> During class definition, the Controller eagerly extracts all relevant metadata
> to populate the Static Service Provider Registry, including:

>     * Header-level static implements and implements declarations.
>     * Service binding descriptors from module-info.class .
>     * META-INF/services/ provider-configuration files.

> Hierarchical Precedence Resolution: To ensure deterministic binding, the
> Controller resolves call sites to their most specific service provider via a
> waterfall dispatch model:

>    1. Tier 1: Type Specialization: Most specific generic match wins , applying the
>    same scrutiny and rules currently used for existing static overloaded method
>     resolution.
>    2. Tier 2: Physical Locality: Provider in the same file (.jar/.class) as the
>     caller wins.
>     3. Tier 3: Loader Proximity: Nearest ClassLoader in the delegation path wins.
>    4. Tier 4: Modular Topology: Internal > Explicit > java.base > Transitive >
>     Automatic .
>     5. Tier 5: Sequential Order: Final tie-breaker via Classpath order.

> 4. Coherence, The Orphan Rule, and Quarantining
> To achieve the type-safety of a trait system, we enforce an adapted Orphan Rule
> : A module (or package on the classpath) must own either the service interface
> or the target type to define an implementation.

>     * Coherence Enforcement: Violations in modular code trigger a LinkageError .
>    * Behavioral Continuity: Violations in classpath code trigger a load-time
>    warning and the provider is quarantined from the Static Registry. To ensure
>    continuity, quarantined providers remain accessible via existing
>    java.util.ServiceLoader API calls , protecting legacy iteration-based discovery
>     while ensuring the integrity of the new link-time dispatch.

> 5. Performance and AOT Considerations
> This model transforms ServiceLoader into a link-time resolver. JIT compilers can
> treat service calls as direct invokestatic instructions, enabling aggressive
> optimization. This is highly compatible with Project Leyden and GraalVM , as
> precedence can be "baked" into the binary during AOT compilation.

> Conclusion
> By transitioning ServiceLoader to a link-time resolver, we provide a type-safe,
> high-performance path for algebraic types and witness-based generics. This
> allows Java to "grow" through libraries—fulfilling the goals of both Darcy and
> Goetz—while maintaining the performance and stability characteristics of the
> modern JVM.

> Thoughts?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20260128/ff52b842/attachment.htm>


More information about the amber-dev mailing list