Skip to content

Conversation

@jerboaa
Copy link
Contributor

@jerboaa jerboaa commented Oct 10, 2025

Please review this revised version of getting rid of jlong and julong in internal HotSpot code. The single remaining usage is using os::elapsed_counter() which I think is still ok. This refactoring is for the container detection code to (mostly) do away with negative return values.

It gets rid of the trifold-use of return value: 1.) error, 2) unlimited values 3) actual numbers/values/limits. Instead, all container related values are now being read from the interface files as uint64_t and afterwards interpreted in the way that make sense for the API implementations. For example, cpu values will essentially be treated as ints as before, potentially returning a negative value -1 for unlimited. For memory sizes the type physical_memory_size_type has been chosen. When there is no limit for a specific memory size a value value_unlimited is being returned.

All error cases have been changed to returning false in the API functions (and no value is being set in the passed in reference for the value). The effect of this is that all container related functions now return a bool and require a reference to be passed in for the value that is being asked for.

All usages of the API have been changed to use the revised API. There is no more usages for OSCONTAINER_ERROR (`-2) in HotSpot code.

While working on this, I've noticed that there are still some calls deep in the cgroup subsystem code to query "machine" info (e.g. os::Linux::active_processor_count()). I've filed JDK-8369503 to get this cleaned-up as this patch was already getting large.

Testing (looking good):

  • GHA
  • All container tests (including problem listed ones) on Linux x86_64 with cg v1 and cg v2. See this comment below.
  • Some ad-hoc manual testing in containers using JFR (jdk.SwapSpace event) and VM.info diagnostic command.

Thoughts? Opinions?


Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed (2 reviews required, with at least 1 Reviewer, 1 Author)

Issue

  • JDK-8365606: Container code should not be using jlong/julong (Enhancement - P4)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/27743/head:pull/27743
$ git checkout pull/27743

Update a local copy of the PR:
$ git checkout pull/27743
$ git pull https://git.openjdk.org/jdk.git pull/27743/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 27743

View PR using the GUI difftool:
$ git pr show -t 27743

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/27743.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Oct 10, 2025

👋 Welcome back sgehwolf! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Oct 10, 2025

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@openjdk openjdk bot added the hotspot hotspot-dev@openjdk.org label Oct 10, 2025
@openjdk
Copy link

openjdk bot commented Oct 10, 2025

@jerboaa The following label will be automatically applied to this pull request:

  • hotspot

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@jerboaa
Copy link
Contributor Author

jerboaa commented Oct 10, 2025

Testing details:

cgroup v2 F42 (docker):

Passed: containers/cgroup/CgroupSubsystemFactory.java
Passed: containers/cgroup/TestContainerized.java
Passed: containers/docker/DockerBasicTest.java
Passed: containers/docker/ShareTmpDir.java
Passed: containers/docker/TestContainerInfo.java
Passed: containers/docker/TestCPUAwareness.java
Passed: containers/docker/TestCPUSets.java
Passed: containers/docker/TestJcmd.java
Passed: containers/docker/TestJcmdWithSideCar.java
Passed: containers/docker/TestJFREvents.java
Passed: containers/docker/TestJFRNetworkEvents.java
Passed: containers/docker/TestJFRWithJMX.java
Passed: containers/docker/TestLimitsUpdating.java
Passed: containers/docker/TestMemoryAwareness.java
Passed: containers/docker/TestMemoryWithCgroupV1.java
Passed: containers/docker/TestMemoryWithSubgroups.java
Passed: containers/docker/TestMisc.java
Passed: containers/docker/TestPids.java
Passed: containers/systemd/SystemdMemoryAwarenessTest.java
Passed: jdk/internal/platform/cgroup/CgroupV1SubsystemControllerTest.java
Passed: jdk/internal/platform/cgroup/CgroupV2SubsystemControllerTest.java
Passed: jdk/internal/platform/cgroup/TestCgroupMetrics.java
Passed: jdk/internal/platform/cgroup/TestCgroupSubsystemController.java
Passed: jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java
Passed: jdk/internal/platform/cgroup/TestSystemSettings.java
Passed: jdk/internal/platform/docker/TestDockerBasic.java
Passed: jdk/internal/platform/docker/TestDockerCpuMetrics.java
Passed: jdk/internal/platform/docker/TestDockerMemoryMetrics.java
Passed: jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java
Passed: jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java
Passed: jdk/internal/platform/docker/TestLimitsUpdating.java
Passed: jdk/internal/platform/docker/TestPidsLimit.java
Passed: jdk/internal/platform/docker/TestSystemMetrics.java
Passed: jdk/internal/platform/docker/TestUseContainerSupport.java
Test results: passed: 34

cgroup v2 F39 (docker):

Passed: containers/cgroup/CgroupSubsystemFactory.java
Passed: containers/cgroup/TestContainerized.java
Passed: containers/docker/DockerBasicTest.java
Passed: containers/docker/ShareTmpDir.java
Passed: containers/docker/TestContainerInfo.java
Passed: containers/docker/TestCPUAwareness.java
Passed: containers/docker/TestCPUSets.java
Passed: containers/docker/TestJcmd.java
Passed: containers/docker/TestJcmdWithSideCar.java
Passed: containers/docker/TestJFREvents.java
Passed: containers/docker/TestJFRNetworkEvents.java
Passed: containers/docker/TestJFRWithJMX.java
Passed: containers/docker/TestLimitsUpdating.java
Passed: containers/docker/TestMemoryAwareness.java
Passed: containers/docker/TestMemoryWithCgroupV1.java
Passed: containers/docker/TestMemoryWithSubgroups.java
Passed: containers/docker/TestMisc.java
Passed: containers/docker/TestPids.java
Passed: containers/systemd/SystemdMemoryAwarenessTest.java
Test results: passed: 19

cgroup v1 RHEL 8 (podman):

Passed: containers/cgroup/CgroupSubsystemFactory.java
Passed: containers/cgroup/TestContainerized.java
Passed: containers/docker/DockerBasicTest.java
Passed: containers/docker/ShareTmpDir.java
Passed: containers/docker/TestContainerInfo.java
Passed: containers/docker/TestCPUAwareness.java
Passed: containers/docker/TestCPUSets.java
Passed: containers/docker/TestJcmd.java
Passed: containers/docker/TestJcmdWithSideCar.java
Passed: containers/docker/TestJFREvents.java
Passed: containers/docker/TestJFRNetworkEvents.java
Passed: containers/docker/TestJFRWithJMX.java
Passed: containers/docker/TestLimitsUpdating.java
Passed: containers/docker/TestMemoryAwareness.java
Passed: containers/docker/TestMemoryWithCgroupV1.java
Passed: containers/docker/TestMemoryWithSubgroups.java
Passed: containers/docker/TestMisc.java
Passed: containers/docker/TestPids.java
Passed: containers/systemd/SystemdMemoryAwarenessTest.java
Test results: passed: 19; skipped: 1

Note: The skipped test on RHEL 8 is TestContainerInfo which checks cgv2 functionality only.

@jerboaa
Copy link
Contributor Author

jerboaa commented Oct 10, 2025

/label add hotspot-jfr

@openjdk openjdk bot added the hotspot-jfr hotspot-jfr-dev@openjdk.org label Oct 10, 2025
@openjdk
Copy link

openjdk bot commented Oct 10, 2025

@jerboaa
The hotspot-jfr label was successfully added.

@jerboaa jerboaa marked this pull request as ready for review October 10, 2025 13:33
@openjdk openjdk bot added the rfr Pull request is ready for review label Oct 10, 2025
@mlbridge
Copy link

mlbridge bot commented Oct 10, 2025

Webrevs

@jerboaa
Copy link
Contributor Author

jerboaa commented Oct 10, 2025

GHA test failure on Windows x64 is unrelated (this is a Linux only patch):
gc/shenandoah/oom/TestThreadFailure

@dholmes-ora
Copy link
Member

There seems to be some collision here with JDK-8367319

@jerboaa
Copy link
Contributor Author

jerboaa commented Oct 13, 2025

There seems to be some collision here with JDK-8367319

Thanks, yes, I'm aware. We'll resolve conflicts once we know which one goes in first.

@jerboaa
Copy link
Contributor Author

jerboaa commented Oct 24, 2025

Could anybody please help review this! Thank you.

@jerboaa
Copy link
Contributor Author

jerboaa commented Oct 24, 2025

/reviewers 2

@openjdk
Copy link

openjdk bot commented Oct 24, 2025

@jerboaa
The total number of required reviews for this PR (including the jcheck configuration and the last /reviewers command) is now set to 2 (with at least 1 Reviewer, 1 Author).

@theRealAph
Copy link
Contributor

I'm not surprised about the lack of reviews because it's long and the result is rather ugly. (Sorry, but I had to say it.)

This is less jarring to read:

struct Result {
  const int _value; const bool _ok;
  Result(int value, bool ok) : _value(value), _ok(ok) {}
};

...

Result CgroupSubsystem::active_processor_count() {
  ...
  cpu_count = os::Linux::active_processor_count();
  if (!CgroupUtil::processor_count(contrl->controller(), cpu_count, value)) {
    return Result(value, false);
  }
  assert(value > 0 && value <= cpu_count, "must be");
  // Update cached metric to avoid re-reading container settings too often
  cpu_limit->set_value(value, OSCONTAINER_CACHE_TIMEOUT);

  return Result(value, true);
}

called as:

  auto [result, ok] = cgroup_subsystem->active_processor_count();
  if (ok) ...

@caspernorrbin
Copy link
Member

caspernorrbin commented Oct 24, 2025

I'm currently looking at this, just as a quick FYI.

I'm fine with the proposed interface as it is (boolean return + passed reference). Since the adjacent os functions recently changed to use this interface, and the disproportionate (to me) amount of bikeshedding it took to reach a consensus on that, introducing yet another interface here, for what's essentially a subcomponent, doesn't make much sense. It's clearer if the whole os stack sticks to the same interface.

@tstuefe
Copy link
Member

tstuefe commented Oct 24, 2025

I'm currently looking at this, just as a quick FYI.

I'm fine with the proposed interface as it is (boolean return + passed reference). Since the adjacent os functions recently changed to use this interface, and the disproportionate (to me) amount of bikeshedding it took to reach a consensus on that, introducing yet another interface here, for what's essentially a subcomponent, doesn't make much sense. It's clearer if the whole os stack sticks to the same interface.

I agree. Its not pretty, but consistent with what we did elsewhere. Nobody wants to do that discussion again.

Copy link
Member

@tstuefe tstuefe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly looks good to me. Some remnants of raw UINT64_FORMAT are left. I did not see any type clashes.

I hold off the final review until it is clear that the interfaces are agreed upon.

bool CgroupSubsystem::active_processor_count(int& value) {
int cpu_count;
int result;
int result = -1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not get rid of result and use value throughout like you did in the cached case?

return false; \
} \
log_trace(os, container)(log_string " is: " JULONG_FORMAT, retval); \
log_trace(os, container)(log_string " is: " UINT64_FORMAT, retval); \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and in other places: don't use raw UINT64_FORMAT; use PHYS_MEM_TYPE_FORMAT instead.

is_ok = controller->read_string(filename, retval, buf_size); \
if (!is_ok) { \
log_trace(os, container)(log_string " failed: %d", OSCONTAINER_ERROR); \
log_trace(os, container)(log_string " failed: -2"); \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change? Did the constant value change?

@theRealAph
Copy link
Contributor

I agree. Its not pretty, but consistent with what we did elsewhere. Nobody wants to do that discussion again.

Sorry, I was unaware of any previous discussion. I was suggesting a less impactful way to make the change, taking advantage of the recent adoption of C++17, which allows for cleaner code. But I won't stand in the way of consensus.

@stefank
Copy link
Member

stefank commented Oct 27, 2025

I agree. Its not pretty, but consistent with what we did elsewhere. Nobody wants to do that discussion again.

Sorry, I was unaware of any previous discussion. I was suggesting a less impactful way to make the change, taking advantage of the recent adoption of C++17, which allows for cleaner code. But I won't stand in the way of consensus.

FWIW, I'd be interested in seeing a small example of what that would look like with C++17. There were a lot of discussion about the style, but it wasn't because we wanted to figure out the color of the bike shed but rather how to write safer code that makes it less likely to accidentally introduce bugs because of type conflation.

@theRealAph
Copy link
Contributor

it wasn't because we wanted to figure out the color of the bike shed but rather how to write safer code that makes it less likely to accidentally introduce bugs because of type conflation.

This. A function that returns its value as a side effect on a reference parameter is (at best) a code smell.

Copy link
Contributor

@fitzsim fitzsim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a reviewer. This looks good to me, overall. I commented with some items to consider.

* All results of division are rounded up to the next whole number.
*
* If quotas have not been specified, return the
* number of active processors in the system.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This paragraph uses the "return" language that you adjusted in the next paragraph. It should probably also refer to the reference argument instead.

* If quotas have not been specified, return the
* number of active processors in the system.
*
* If quotas have been specified, the resulting number
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny nit, but "the resulting number" => "the number", since you say "the result reference" on the next line.

cpu_count = os::Linux::active_processor_count();
result = CgroupUtil::processor_count(contrl->controller(), cpu_count);
if (!CgroupUtil::processor_count(contrl->controller(), cpu_count, result)) {
return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value will be returned unchanged from its passed-in value here. I wonder if it would be safer to explicitly set it to 0 when returning false. Also, could value be given an unsigned type, like uint64_t?

* Return the limit of available memory for this process.
* Return the limit of available memory for this process in the provided
* physical_memory_size_type reference. If there was no limit value set in the underlying
* interface files value_unlimited is returned.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think quote value_unlimited here to hint that it is a constant defined elsewhere.

Can the limit ever be 0, and if not, should there be a new assert for > 0 like for cpu_count?

* Determine the memory and swap limit metric. Returns a positive limit value strictly
* lower than the physical memory and swap limit iff there is a limit. Otherwise a
* negative value is returned indicating the determined status.
* Determine the memory and swap limit metric. Returns a positive limit value or
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Returns" language should probably be updated here too.

// cast to int since the read value might be negative
// and we want to avoid logging -1 as a large unsigned value.
int quota_int = (int)quota;
int quota_int = static_cast<int>(quota);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like quota is either a positive number or disabled. I wonder if result can be treated as a uint64_t, and this log message special-cased to detect -1 read from /cpu.cfs_quota_us as disabled. I guess the calling code would need another way to differentiate "disabled" from other values... maybe with 0? Just a thought to maybe simplify the type logic here. Likewise for period and shares.

Copy link
Member

@caspernorrbin caspernorrbin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking this on! I think this is a solid improvement, and it's great to finally see the Java types phased out. I had a few thoughts/comments, mostly around the os-level code and the logging of constants, since those constants don't really have much meaning anymore. Otherwise great work!

Comment on lines +2210 to +2215
physical_memory_size_type mem_usage = 0;
if (!OSContainer::memory_usage_in_bytes(mem_usage)) {
return false;
}
value = mem_usage;
return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we collapse this and just set the value reference directly instead in the container functions? Something like:

if (OSContainer::is_containerized()) {
  return OSContainer::memory_usage_in_bytes(mem_usage);
}

Comment on lines +217 to +220
physical_memory_size_type avail_mem = 0;
if (OSContainer::is_containerized() && OSContainer::available_memory_in_bytes(avail_mem)) {
log_trace(os)("available container memory: " PHYS_MEM_TYPE_FORMAT, avail_mem);
value = avail_mem;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be able to pass in value directly instead of using avail_mem.

Comment on lines +258 to +261
physical_memory_size_type free_mem = 0;
if (OSContainer::is_containerized() && OSContainer::available_memory_in_bytes(free_mem)) {
log_trace(os)("free container memory: " PHYS_MEM_TYPE_FORMAT, free_mem);
value = free_mem;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be able to pass in value directly instead of using free_mem.

Comment on lines 318 to 348
if (OSContainer::is_containerized()) {
jlong mem_swap_limit = OSContainer::memory_and_swap_limit_in_bytes();
jlong mem_limit = OSContainer::memory_limit_in_bytes();
if (mem_swap_limit >= 0 && mem_limit >= 0) {
jlong delta_limit = mem_swap_limit - mem_limit;
if (delta_limit <= 0) {
value = 0;
physical_memory_size_type mem_limit = 0;
physical_memory_size_type mem_swap_limit = 0;
if (OSContainer::memory_limit_in_bytes(mem_limit) &&
OSContainer::memory_and_swap_limit_in_bytes(mem_swap_limit) &&
mem_limit != value_unlimited &&
mem_swap_limit != value_unlimited) {
if (mem_limit >= mem_swap_limit) {
value = 0; // no swap, thus no free swap
return true;
}
jlong mem_swap_usage = OSContainer::memory_and_swap_usage_in_bytes();
jlong mem_usage = OSContainer::memory_usage_in_bytes();
if (mem_swap_usage > 0 && mem_usage > 0) {
jlong delta_usage = mem_swap_usage - mem_usage;
if (delta_usage >= 0) {
jlong free_swap = delta_limit - delta_usage;
value = free_swap >= 0 ? static_cast<physical_memory_size_type>(free_swap) : 0;
physical_memory_size_type swap_limit = mem_swap_limit - mem_limit;
physical_memory_size_type mem_swap_usage = 0;
physical_memory_size_type mem_usage = 0;
if (OSContainer::memory_and_swap_usage_in_bytes(mem_swap_usage) &&
OSContainer::memory_usage_in_bytes(mem_usage)) {
physical_memory_size_type swap_usage = value_unlimited;
if (mem_usage > mem_swap_usage) {
swap_usage = 0; // delta usage must not be negative
} else {
swap_usage = mem_swap_usage - mem_usage;
}
// free swap is based on swap limit (upper bound) and swap usage
if (swap_usage >= swap_limit) {
value = 0; // free swap must not be negative
return true;
}
value = swap_limit - swap_usage;
return true;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole function is getting a bit too long in my opinion.
Maybe everything inside the if OSContainer::is_containerized() {} could be moved into a new function OSContainer::available_swap_in_bytes, similar to the already existing OSContainer::available_memory_in_bytes. That way, we could abstract away all the OSContainer calls.

The only consequence would be that the log_trace wouldn't work any more. I couldn't find any test that depends on the exact output, so it could perhaps be split up instead.

Comment on lines +4860 to 4863
int active_cpus = os::Linux::active_processor_count();
if (OSContainer::is_containerized() && OSContainer::active_processor_count(active_cpus)) {
log_trace(os)("active_processor_count: determined by OSContainer: %d",
active_cpus);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When running containerized, we would now always fetch the os cpu count at least once.

CgroupSubsystem::active_processor_count, which this calls down to has the cache to actively avoid getting the cpu count too frequently, and only gets the number of cpus with os::Linux::active_processor_count when the cache expires.

I don't know if this is still an issue today, but since it's there I still think we should avoid getting the cpus if unnecessary.

Comment on lines 107 to 115
/* cpu_quota
*
* Return the number of microseconds per period
* process is guaranteed to run.
*
* return:
* quota time in microseconds
* -1 for no quota
* OSCONTAINER_ERROR for not supported
* true if the result reference has been set
* false on error
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The beginning part of the comment isn't updated to mention the result reference, unlike the other comments.

if (!is_ok) {
log_trace(os, container)("CPU Usage failed: %d", OSCONTAINER_ERROR);
return OSCONTAINER_ERROR;
log_trace(os, container)("CPU Usage failed: -2");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to keep the -2 here? Or could we perhaps change to a better message?

if (!reader()->read_number_handle_max("/memory.swap.max", swap_limit_val)) {
// Some container tests rely on this trace logging to happen.
log_trace(os, container)("Swap Limit failed: %d", OSCONTAINER_ERROR);
log_trace(os, container)("Swap Limit failed: -2");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to keep the -2 here? Or could we perhaps change to a better message?

Comment on lines +377 to +379
* Calculate the maximum number of tasks available to the process. Set the
* value in the passed in 'value' reference. The value might be -1 when
* there is no limit.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can we get -1? Or do you mean (uint64_t)-1?

// intentionally not using the macro so as to not log a
// negative value as a large unsiged int
if (!reader()->read_number("/cpu.cfs_quota_us", quota)) {
log_trace(os, container)("CPU Quota failed: -2");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to keep the -2 here? Or could we perhaps change to a better message?

@jerboaa
Copy link
Contributor Author

jerboaa commented Oct 30, 2025

it wasn't because we wanted to figure out the color of the bike shed but rather how to write safer code that makes it less likely to accidentally introduce bugs because of type conflation.

This. A function that returns its value as a side effect on a reference parameter is (at best) a code smell.

Thanks for the comments. So what's the consensus then? As far as API surface is concerned I've modelled it after JDK-8357086. It introduces the side-effect/code smell issue. Do we want to re-open this discussion or proceed with this here. It's not clear to me.

@openjdk
Copy link

openjdk bot commented Nov 4, 2025

@jerboaa this pull request can not be integrated into master due to one or more merge conflicts. To resolve these merge conflicts and update this pull request you can run the following commands in the local repository for your personal fork:

git checkout jdk-8365606-jlong-julong-refactor
git fetch https://git.openjdk.org/jdk.git master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push

@openjdk openjdk bot added the merge-conflict Pull request has merge conflict with target branch label Nov 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hotspot hotspot-dev@openjdk.org hotspot-jfr hotspot-jfr-dev@openjdk.org merge-conflict Pull request has merge conflict with target branch rfr Pull request is ready for review

Development

Successfully merging this pull request may close these issues.

7 participants