Fwd: Feedback about StableValues(Preview)
Swaranga Sarma
sarma.swaranga at gmail.com
Tue Sep 2 23:40:26 UTC 2025
I see the ask as slightly different from stable values. Stable values are
really two things - a compile time constant that can be inlined and is
always lazily initialized exactly once. This ask is for the second part -
being able to lazily initialize a value with the same exactly once
guarantees without the restriction that the keys must be known at compile
time. I have personally used Guava's Suppliers.memoize(Supplier<T> s) or
even ConcurrenthashMap's computeIfAbsent for my use-cases and in those I
didn't really care about inlining/folding, just the lazy aspect of it.
To me it is not a huge deal of not having a language or even a standard
Java API for it; I have managed without it so far.
Regards
Swaranga
On Tue, Sep 2, 2025 at 4:15 PM Maurizio Cimadamore <
maurizio.cimadamore at oracle.com> wrote:
> Hi David,
> Thanks for your feedback.
>
> The factories that we provide, like StableValue::list and StableValue::map
> cover common cases where the list/map elements are known upfront, but
> should be computed lazily.
>
> In other words you might think of these factories as lazy variants of
> List::of and Map::of. Both kinds of factories return an unmodifiable
> collection -- that is a collection whose size is fixed, and that rejects
> update operations.
>
> I understand that you would like to create a "stable" map, whose
> key/values are not known upfront -- more specifically, where the keys are
> only known dynamically.
>
> I believe in these cases the "win" for using a stable map in the first
> place is much less obvious. If the map can grow dynamically (e.g. because
> you don't know how many entries you might be adding to it) you are probably
> looking at an implementation that has some way to "resize" itself -- which
> makes using something like a stable construct much harder. For instance,
> adding new entries on a map might cause the underlying array of buckets to
> be reallocated, and existing entries to be rehashed in the new (larger)
> bucket array. This means that the bucket array itself will need to be
> updated several times during the lifecycle of the map, making it not stable
> (remember: stable means "updated at most once").
>
> If some constraints are relaxed, e.g. maybe you know how many entries you
> are going to add in your map -- that might make the problem easier, as now
> we're back in a situation where we now the size of the underlying storage.
> For instance one can have a specialized hash table implementation backed by
> a linear array (of an appropriate size), and then use linear probing to
> store entries in the linear array. Since the size is bounded, the size of
> the entries linear array is also bounded, and we can then make that linear
> array stable (e.g. use a stable list).
>
> Since such a "fixed size" hash map would be quite specialized, we did not
> see yet enough motivation for adding it to the JDK -- especially given that
> developers should be able to define such constructs on top of the
> StableValue API (in fact _all_ the existing provided factories are defined
> in terms of the Stable Value API).
>
> But it's not just about whether the size is known or not -- in order for
> the JVM to be able to apply any sort of constant-folding optimization to
> the map access, you need the key to be a constant (e.g. either some
> compile-time constant, or the value of a static final field, or the
> contents of some other stable value). Only then we can fold the entire map
> access expression (if we're lucky). But in the example you provide, the key
> provided to Map::get is just a random class name you get from the current
> stack. So there's very little for the JIT to optimize here. If the input
> (the key) is not known, then the access expression (Map::get) cannot be
> optimized.
>
> In other words, the case of a fully dynamic list/map that you propose just
> doesn't seem a great fit for stability, in the sense that you likely won't
> get any performance improvement (over a concurrent hash map) by using some
> sort of stable map there.
>
> Maurizio
>
>
> On 02/09/2025 02:45, david Grajales wrote:
>
>
>
> ---------- Forwarded message ---------
> De: david Grajales <david.1993grajales at gmail.com>
> Date: lun, 1 sept 2025 a la(s) 8:43 p.m.
> Subject: Feedback about StableValues(Preview)
> To: <core-libs-dev at openjdk.org>
>
>
> Subject: Feedback and Questions on JEP 8359894 - Stable Values API
>
> Dear Java core-libs development team,
>
> Please accept my sincere gratitude and compliments for your ongoing
> dedication to improving the Java platform. The continuous innovation and
> thoughtful evolution of Java is truly appreciated by the developer
> community.
>
> I have been experimenting with the Stable Values API (JEP 8359894) in a
> development branch of a service at my company, and I would like to share
> some observations and seek your guidance on a particular use case.
>
>
> Current Implementation
>
> Currently, I have a logging utility that follows a standard pattern for
> lazy value computation:
>
> class DbLogUtility {
> private static final ConcurrentMap<String, Logger> loggerCache = new
> ConcurrentHashMap<>();
>
> private DbLogUtility(){}
>
> private static Logger getLogger() {
> var className =
> Thread.currentThread().getStackTrace()[3].getClassName();
> return loggerCache.computeIfAbsent(className,
> LoggerFactory::getLogger);
> }
> public static void logError(){
> //.... implementation detail
> }
> }
>
> Challenge with Stable Values API
>
> When attempting to migrate this code to use the Stable Values API, I
> encountered a fundamental limitation: the API requires keys to be known at
> compile time. The current factory methods (StableValue.function(Set<K>,
> Function) and StableValue.intFunction(int, IntFunction)) expect
> predefined key sets or bounded integer ranges.
>
> This design constraint makes it challenging to handle dynamic key
> discovery scenarios, which are quite common in enterprise applications for:
>
> - Logger caching by dynamically discovered class names
> - Configuration caching by runtime-determined keys
> - Resource pooling with dynamic identifiers
> - Etc.
>
>
> Questions and Feedback
>
> 1. *Am I missing an intended usage pattern?* Is there a recommended
> approach within the current API design for handling dynamic key discovery
> while maintaining the performance benefits of stable values?
> 2. Would you consider any of these potential enhancements:
> - Integration of stable value optimizations directly into existing
> collection APIs (similar to how some methods have been added to List and
> Map interfaces for better discoverability)
> - A hybrid approach that provides stable value benefits for
> dynamically discovered keys
> 3. Do you envision the Stable Values API as primarily serving
> compile-time-known scenarios, with dynamic use cases continuing to rely on
> traditional concurrent collections?
>
> Thank you for your time and consideration. I would be grateful for any
> guidance or clarification you might provide on these questions. If there
> are planned enhancements or alternative patterns I should consider, I would
> very much appreciate your insights.
>
> Best regards, and always yours.
>
> David Grajales Cárdenas.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20250902/d28559b6/attachment-0001.htm>
More information about the amber-dev
mailing list