JDK-8305590 : Remove nothrow exception specifications from operator new
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 21
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2023-04-04
  • Updated: 2025-06-13
  • Resolved: 2023-04-23
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 21
21 b20Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Only allocation functions (e.g. `operator new`) that can actually return null should have nothrow exception specs.  Having unnecessary nothrow exception specs causes the compiler to generate useless null checks.

JDK-8021954 added `throw()` exception specifications to all allocation functions provided by HotSpot.  This was in response to a metaspace allocation failure returning null, leading to a crash.

The standard (C++03 5.3.4/13, C++14 5.3.4/15) provides the rationale for that change.  An allocation function can report allocation failure either by returning null (when it must have a nothrow exception specification), or by throwing `std::bad_alloc` (so obviously must not be declared as non-throwing).

The purpose of the nothrow exception spec is to allow a `new` expression to detect a potential null allocation, for which it must itself return null, without attempting initialization.

However, the JDK-8021954 change was an over-response to the problem.  We only need nothrow exception spes for allocation functions that return null to indicate failure.  Many (nearly all?) of our `operator new` functions indicate allocation failure by terminating the program rather than returning null.  This is typically determined by a given `operator new` passing the appropriate AllocFailStrategy to the underlying implementation.  `Metaspace::allocate` returns null to indicate allocation failure, and many of the callers (including the allocation functions for MetaspaceObj and Klass) just pass that null result along to their callers for appropriate handling.

We're also unnecessarily using the gcc option `-fcheck-new`.  That option is redundant when the allocation function has a nothrow spec (indicating it can return null), because the compiler will generate the null check regardless of that option.  And if the allocation function never returns null (indicated by not having a nothrow spec), then that option is just making the compiler generate a useless null check.

StackObj::operator new will need additional adjustment.  Perhaps it can just have the allocation and deallocation functions declared deleted?

Comments
A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/13498 Date: 2023-04-17 17:09:44 +0000
13-06-2025

Changeset: 0f51e632 Author: Afshin Zafari <Afshin.zafari@oracle.com> Committer: Jesper Wilhelmsson <jwilhelm@openjdk.org> Date: 2023-04-23 15:20:18 +0000 URL: https://git.openjdk.org/jdk/commit/0f51e6326373ff7d4a4d9a0e3a2788401f73405d
23-04-2023

[~dholmes] The effect of the nothrow spec is to make the compiler check the result for null. What possible bug would make such a check necessary for a function that never returns null? It's possible the referenced article was misleading or contained misinformation. That's hard to know without being able to read it (and I spent a bit of time trying but failing to find it, because I was curious). But having just read the Visual Studio documentation for /Zc:throwingNew (see JDK-8306579) I can easily believe that's the problem.
20-04-2023

[~dholmes] I don't see how it could have been necessary at the time. One can infer what that blog post said without having access - it was an explanation of the requirement to mark allocation functions noexcept if they can return null. It has never made sense for an allocation function to be noexcept even though it never returns null. That just causes the compiler to generate useless null checks. No change to clang would have changed that. But now, due to improved value propagation, those useless null checks are causing problems. Aside: The purpose of gcc's `-fcheck-new` is to request the compiler generate null checks for allocation functions that aren't noexcept. The point seems to be that one may be dealing with allocation functions that can return null but don't have the required noexcept to indicate that, but for whatever reason you can't fix that missing noexcept. Maybe it's in 3rd-party code that you aren't allowed to modify, or something like that.
20-04-2023

[~kbarrett] I understand that is how it is viewed now, but it seemed to be deemed necessary at the time - but without the original motivating article I can't confirm one way or the other. I presume clang has changed in the last 10 years. :)
20-04-2023

[~kbarrett] Maybe there was a bug in clang? My assumption is that something in that article led to the conclusion that "empty exception throw() specifications must be added to all user-defined operator new()'s.".
20-04-2023

[~dholmes] That's the "over-response" mentioned in the description. Not all user-defined operator new()'s needed the empty exception specification. Only those that report failure by returning null need it. That empty exception spec is the signal to the language implementation that it needs to check for a null return and behave accordingly (see refs to the Standard). Looking at change history, I think that at the time JDK-8021954 went in we already had in place some things like AllocFailStrategy (JDK-8000617), so even back then we had operator new()s that didn't report failure by returning null, so did not need an empty exception spec.
19-04-2023

The summary from JDK-8021954 was: "The clang++ compiler does not support the -fcheck-new option. To obtain similiar functionality when building Hotspot with clang++, empty exception throw() specifications must be added to all user-defined operator new()'s. " Unfortunately the article explaining this need no longer seems to exist and it was nearly 10 years ago.
19-04-2023