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