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

Ethan McCue ethan at mccue.dev
Wed Jan 28 22:25:18 UTC 2026


Not in what I just wrote, no.

On Wed, Jan 28, 2026, 5:08 PM Ron Pressler <ron.pressler at oracle.com> wrote:

> What is the problem you’re trying to point out? Is it “something that can
> be expressed in Java could be expressed more elegantly”?
>
> I’m not saying this is a disqualified problem, but I’d like to understand
> if there’s a problem here that can be stated without hinting at a specific
> solution (such as "mechanism X and Y could be unified"), as in “processing
> pure data in Java is cumbersome”, or “calling native code from Java is
> tedious and error-prone”, or “it’s difficult in Java to clear,
> debuggable/proflable concurrent code that scales well”, or “processing some
> Java collections incurs many cache-misses that impact performance”, or
> “propagating timeouts and cancellation across dependent tasks is
> difficult”, or “correctly freeing OS resources in the presence of
> exceptions is difficult” etc. (but with more elaboration, obviously).
>
> — Ron
>
> > On 28 Jan 2026, at 17:50, Ethan McCue <ethan at mccue.dev> wrote:
> >
> > I am sympathetic because "service loader" was also what entered my mind
> when thinking about "implementation of interface made magically
> discoverable."
> >
> > Right now an implementation of interface provided via the service loader
> >
> > 1. Can have 0-N implementations provided
> > 2. Has these provided interfaces specified in module info via "provides
> ... with ...;"
> >
> > An implementation of an interface provided via a witness
> >
> > 1. Should only have 1 implementation for a type being "summoned"
> > 2. Has these provided interfaces specified inside a class, in the
> current prototype via "__witness"
> > 3. Relies on the interface for which a witness is provided having a
> generic parameter
> >
> > My gut feeling is that these mechanisms *could* be unified
> >
> >      provides Formatter for List<String> with SomeClass;
> >
> > And that, if they aren't, we'd start to see things like
> >
> >     summon(Logger<App>).log(...)
> >
> > But equally I find it hard to
> >
> > 1. Reason about how moving "witness registration" from classes to a
> module info would affect things like witness resolution or "unconditional
> provides."
> > 2. Justify it beyond a vague feeling
> >
> >
> >
> > On Wed, Jan 28, 2026, 11:56 AM Ron Pressler <ron.pressler at oracle.com>
> wrote:
> > The hardest part in designing and evolving a language is deciding which
> problems are important enough to merit a solution in the language and how
> their priorities compares to other problems. It’s the hardest part because
> the language team are expert at coming up with solutions, but they may not
> always know what problems people enoucnter in the field, how frequently
> they encounter them, and how they work around them today.
> >
> > I’m sure there is some problem hidden here and in your previous post,
> but it is not articulated well and is hidden in a poposed solution, even
> though no solution is even worth exploring before understanding the
> problem. And so the best way to get to a solution is for you to focus on
> the problem and only on the problem.
> >
> > What was the problem you *personally* ran into? How bad were its
> implications? How did you work around it?
> >
> > With the hard part done, the JDK team will then be able to assess its
> severity and think whether it merits a solution in the JDK, if so, where
> (language, libraries, or VM), and how to prioritise it against other
> problems worth tackling. Then they’ll be able to propose a solution, and
> that’s would be the time to try it out and discuss it.
> >
> > — Ron
> >
> >
> >
> > > On 28 Jan 2026, at 00:28, Steffen Yount <steffenyount at gmail.com>
> wrote:
> > >
> > > 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:
> > >     • Tier 1: Type Specialization: Most specific generic match wins,
> applying the same scrutiny and rules currently used for existing static
> overloaded method resolution.
> > >     • Tier 2: Physical Locality: Provider in the same file
> (.jar/.class) as the caller wins.
> > >     • Tier 3: Loader Proximity: Nearest ClassLoader in the delegation
> path wins.
> > >     • Tier 4: Modular Topology: Internal > Explicit > java.base >
> Transitive > Automatic.
> > >     • 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/9153a158/attachment-0001.htm>


More information about the amber-dev mailing list