-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8355369: Remove setAccessible usage for setting final fields in java.util.concurrent #24821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ceArray to use Unsafe rather than Field.setAccessible
|
👋 Welcome back vklang! A progress list of the required criteria for merging this PR into |
|
@viktorklang-ora This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 40 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
|
@viktorklang-ora The following label will be automatically applied to this pull request:
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. |
Webrevs
|
| final Unsafe U = Unsafe.getUnsafe(); | ||
| U.putReference( | ||
| this, | ||
| U.objectFieldOffset(ConcurrentSkipListSet.class, "m"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to compute the offset once and for all and put it in a static final long field?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I originally did that, but the following patch is the "smallest change".
Given that the "original code" obtained the Field instance each call, this is still likely a performance improvement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code has always used getDeclaredField each time so if anyone had run into a performance issue then we should have heard by now. So I think keeping the changes simple and just moving to Unsafe is okay for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine. The main effect of this change is to nearly revert to the pre-VarHandle version of this code.
|
Seems these are used mainly for cloning: is it possible for us to just use |
|
@liach Not sure I understand, could you elaborate a bit? |
|
I guess the intent is just to have the minimal patch to come away from |
It's to move away from using Field.set to mutate non-static final fields. Viktor offered to get this done before the "prepare for final means final" changes. |
I mean that we call the setters in |
|
@viktorklang-ora Before approving, what is the status of the copyright notices? There seem to be no years to update... |
| (ConcurrentSkipListSet<E>) super.clone(); | ||
| clone.setMap(new ConcurrentSkipListMap<E,Object>(m)); | ||
| // Needed to ensure safe publication of setMap() | ||
| VarHandle.releaseFence(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DougLea This might be interesting to you. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we could just change it to return new ConcurrentSkipListSet<>(m). COWAL could be changed to return a new object too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The set only has a map field, and AbstractSet does not define any additional field. The map should be fine too - two fields in AbstractMap are cleared when cloning happens, so recreating a map from a constructor should have the same effect. (Note a significant field head is not cleared upon clone, but seems immediately replaced later in buildFromSorted). Both should still be fine with this new return values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As others have mentioned, clone() needs to be re-checked wrt issuing final field fences. But can be conservatively done so here anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DougLea Yeah. I'd be surprised if clone()-invocations were specially tracked to get a trailing release fence inserted before handing out the instance.
|
@rgiulietti These are the JSR166 files, so I didn't touch the copyright notices. |
Potentially AtomicReferenceArray.readObject could be replaced, the others are clone methods. |
|
Thanks. We can investigate how clone cleanups interact with truly final or strict finals in another issue. |
|
@liach @AlanBateman My proposal here would be to move forward with the proposed changes for now, and then once 25 is branched off there's an opportunity to take a broader look at |
minborg
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these changes look good. Before we integrate, could you please raise an issue with the future improvements of clone() and friends so that we do not forget that?
| (ConcurrentSkipListSet<E>) super.clone(); | ||
| clone.setMap(new ConcurrentSkipListMap<E,Object>(m)); | ||
| // Needed to ensure safe publication of setMap() | ||
| VarHandle.releaseFence(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As others have mentioned, clone() needs to be re-checked wrt issuing final field fences. But can be conservatively done so here anyway.
rgiulietti
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Okay with me. We can also add a non-public constructor to some of these classes and use it from readResolve so that we don't need readObject methods that mutate finals. |
|
/integrate |
|
Going to push as commit 356c4d9.
Your commit was automatically rebased without conflicts. |
|
@viktorklang-ora Pushed as commit 356c4d9. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
This Pull Request replaces the uses of Field + setAccessible to modify final fields in java.util.concurrent with Unsafe.
Progress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/24821/head:pull/24821$ git checkout pull/24821Update a local copy of the PR:
$ git checkout pull/24821$ git pull https://git.openjdk.org/jdk.git pull/24821/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 24821View PR using the GUI difftool:
$ git pr show -t 24821Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/24821.diff
Using Webrev
Link to Webrev Comment