RFR: 8369186: HotSpot Style Guide should permit some uses of the C++ Standard Library [v2]

Kim Barrett kbarrett at openjdk.org
Sat Nov 1 07:34:03 UTC 2025


On Mon, 27 Oct 2025 08:24:41 GMT, Florian Weimer <fweimer at openjdk.org> wrote:

>> We (you and me, @fweimer-rh) discussed this a couple of years ago:
>> https://mail.openjdk.org/pipermail/hotspot-dev/2023-December/082324.html
>> 
>> Quoting from here:
>> https://mail.openjdk.org/pipermail/hotspot-dev/2023-December/083142.html
>> 
>> "
>> Empirically, a recursive initialization attempt doesn't make any attempt to
>> throw. Rather, it blocks forever waiting for a futex signal from a thread that
>> succeeds in the initialization. Which of course will never come.
>> 
>> And that makes sense, now that I've looked at the code.
>> 
>> In __cxa_guard_acquire, with _GLIBCXX_USE_FUTEX, if the guard indicates
>> initialization hasn't yet been completed, then it goes into a while loop.
>> This while loop tries to claim initialization.  Failing that, it checks
>> whether initialization is complete.  Failing that, it does a SYS_futex
>> syscall, waiting for some other thread to perform the initialization.  There's
>> nothing there to check for recursion.
>> 
>> throw_recursive_init_exception is only called if single-threaded (either by
>> configuration or at runtime).
>> "
>> 
>> It doesn't look like there have been any relevant changes in that area since
>> then. So I think there is still not a problem here.
>
> @kimbarrett Sorry, I forgot about the old thread. You can get the exception in a single-threaded scenario, something like this:
> 
> 
> struct S {
>   S() {
>     static S s;
>     *this = s;
>   }
> } global;
> 
> 
> Maybe the actual rule is more like this?
> 
>> Functions that may throw exceptions must not be used, unless individual calls ensure that these particular invocations cannot throw exceptions.

Recursively entering a block-scoped static is undefined behavior. That some
configurations of glibc might throw an exception in that situation (even
despite the caller being compiled with exceptions disabled) seems like a
mistake in glibc, and not really our concern. Our code should avoid such a
situation because it's UB, regardless of whether the actual behavior involves
exceptions or nasal demons.

The exception only gets thrown when the application is single-threaded. But at
least the common way to start java (via the launcher) is already
multi-threaded on entry to Threads::create_vm(). So that case doesn't normally
apply to us anyway.

Also, I really don't think we want people trying to figure out whether a
particular call might or might not throw (neither when writing nor when
reading code).

So no, I don't think the proposed rule should be changed.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/27601#discussion_r2483178071


More information about the serviceability-dev mailing list