Skip to content

Conversation

@rkennke
Copy link
Contributor

@rkennke rkennke commented Jul 4, 2025

I'd like to propose a new Full-GC forwarding scheme for the Serial, Parallel, G1 and Shenandoah GCs.

Primarily, it solves a limitation when compact object headers are turned on: the above mentioned GCs can then not handle heaps > 8TB, and we turn off compact object headers, instead. I realize that this is most likely not an issue in practice for Serial GC (who would want this?). It may be an issue with Parallel and G1 GCs (I know some folks run with Parallel GC on large batch jobs, where latency is not a concern at all. G1 may be useful in the same situation, perhaps). It is an issue with Shenandoah GC, because large heaps is one reason why Shenandoah exists to begin with. (ZGC doesn't have this problem, because it does not have a full-GC.) Given that I think we should make compact object headers on by default in JDK 26, and obsolete the old mode in JDK 27, I think it'd be useful to have the new implementation available now.

Second, it's a first step and preparation towards 4-byte-headers, which I hope to bring into JDK 27. With 4-byte-headers, we only have 9 bits in the header for storing forwarding-pointers during full-GC, and this implementation provides that with minimal overhead.

I've proposed something similar before (see #20605), but this improved implementation is simpler, uses less memory overhead, and has basically no performance impact.

There is a large comment at the top of fullGCForwarding.hpp which explains the algorithm in detail. I am not repeating it here. I'll just state some basic properties:

  • The algorithm exploits the fact that full-GC forwarding happens (mostly) sequentially (within a region/block).
  • It divides the heap into blocks. Given N header bits for addressing, the size of each block is 2^N heap-words. In this change, we have 40 bits - the other bits are two 'lock-bits' to indicate forwarding and 22 compressed-class-bits that we need to protect (that is the point of this patch). This means a block-size of 8TB. (With 4-byte-headers, we will only have 9 bits, therefore the block-size is 2KB).
  • For each such block, we need one word in a forwarding-table to store the base-pointer for that block. The size of that table is 1/(2^N)th of the heap-size in words. In the current proposed change, that 'table' is just a single word for each 8TB. With 4-byte-headers, the table will be 1/512th of the heap size.
  • If necessary (e.g. when the sequential-property is broken, such as on space boundaries, in G1's serial compaction, and when forwarding to the very last word of a block), then we use a fallback-concurrent-hashtable. This happens very rarely and doesn't really affect performance.
  • Speaking of performance: in my measurements I could not see any regressions, performance looks neutral.

In order to facilitate testing and later reduction of the implementation to fewer bits, I template-ized the forwarding table implementation on the number of bits. This allows me to write unit tests that don't take >8TB of heap and stress some of the interesting scenarios, without affecting performance in normal HotSpot product situations.

Testing:

  • In Lilliput 2 (fewer-bits version)
  • tier1-4
  • hotspot_gc

Progress

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

Warnings

 ⚠️ Patch contains a binary file (src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletColor16.gif)
 ⚠️ Patch contains a binary file (src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletColor32.gif)
 ⚠️ Patch contains a binary file (src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletMono16.gif)
 ⚠️ Patch contains a binary file (src/java.desktop/share/classes/javax/swing/beaninfo/images/JAppletMono32.gif)
 ⚠️ Patch contains a binary file (src/java.desktop/share/classes/javax/swing/doc-files/JRootPane-1.gif)
 ⚠️ Patch contains a binary file (test/jdk/javax/rmi/ssl/keystore)
 ⚠️ Patch contains a binary file (test/jdk/javax/rmi/ssl/truststore)
 ⚠️ Patch contains a binary file (test/jdk/sun/net/www/protocol/https/HttpsClient/dnsstore)
 ⚠️ Patch contains a binary file (test/jdk/sun/net/www/protocol/https/HttpsClient/ipstore)

Issue

  • JDK-8361252: Compact Full-GC Forwarding (Enhancement - P4)

Reviewing

Using git

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

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

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 26133

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

Using diff file

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

@bridgekeeper
Copy link

bridgekeeper bot commented Jul 4, 2025

👋 Welcome back rkennke! 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 Jul 4, 2025

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

@openjdk
Copy link

openjdk bot commented Jul 4, 2025

@rkennke The following labels will be automatically applied to this pull request:

  • hotspot
  • shenandoah

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

@openjdk
Copy link

openjdk bot commented Sep 4, 2025

@rkennke 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-8361252
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 Sep 4, 2025
@bridgekeeper
Copy link

bridgekeeper bot commented Sep 9, 2025

@rkennke This pull request has been inactive for more than 8 weeks and will be automatically closed if another 8 weeks passes without any activity. To avoid this, simply issue a /touch or /keepalive command to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

@bridgekeeper
Copy link

bridgekeeper bot commented Nov 5, 2025

@rkennke This pull request has been inactive for more than 16 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the /open pull request command.

@bridgekeeper bridgekeeper bot closed this Nov 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hotspot [email protected] merge-conflict Pull request has merge conflict with target branch shenandoah [email protected]

Development

Successfully merging this pull request may close these issues.

1 participant