-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
8328611: Thread safety issue in com.sun.tools.jdi.ReferenceTypeImpl::classObject #19439
Conversation
The bug is the classic "double-checked-locking" flaw. In general "double-checked-locking" does not work, but in this case, based on how it is used and the java memory model, it can be made to work by making the field volatile. Although the issue could be fixed by making the classObject field volatile, I decided to get rid of the double-checked-locking instead. There is little benefit to using it here (it simply avoids fetching the info twice when there is a race, which is very rare), and leaving it out simplifies the code and reduces overhead for the usual case (when there is no race). Regarding the pre-existing comment:
Yes, they are unique. No they are not created each time. Probably this lack of understanding is why double-checked-locking was used here. The ObjectReference spec is a bit loose on the wording, referring to an ObjectReference as "An object that currently exists in the target VM". However, the implementation is not. VirtualMachineImpl.objectMirror() is used to create all ObjectReference instances, and it only creates one ObjectReference per JDWP objectID. I tested this by making classObject() fetch the ObjectReference on every call and compare the result to the cached value, and they always match. Also, the JDWP spec calls out that each java Object instance has 1 unique objectID. The following is the JDWP spec description of the objectID type. "Uniquely identifies an object in the target VM. A particular object will be identified by exactly one objectID in JDWP commands and replies throughout its lifetime (or until the objectID is explicitly disposed). An ObjectID is not reused to identify a different object unless it has been explicitly disposed, regardless of whether the referenced object has been garbage collected. An objectID of 0 represents a null object. Note that the existence of an object ID does not prevent the garbage collection of the object. Any attempt to access a a garbage collected object with its object ID will result in the INVALID_OBJECT error code. Garbage collection can be disabled with the DisableCollection command, but it is not usually necessary to do so." While looking into this bug I also ran across the similar classLoader() API, and noticed that it did not use synchronized and explained why in a comment. That is where I got the motivation to remove synchronized from classObject(). Then I found a bunch more similar APIs. I cleaned up their comment to be consistent. |
👋 Welcome back cjplummer! A progress list of the required criteria for merging this PR into |
@plummercj 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 155 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 |
@plummercj 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
|
src/jdk.jdi/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java
Outdated
Show resolved
Hide resolved
Thanks for the reviews Serguei and Alex! /integrate |
Going to push as commit 922e312.
Your commit was automatically rebased without conflicts. |
@plummercj Pushed as commit 922e312. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
Fixed "double-checked-locking" bug in
ReferenceImplType.classObject()
. Details in the first comment. Tested with the following:Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/19439/head:pull/19439
$ git checkout pull/19439
Update a local copy of the PR:
$ git checkout pull/19439
$ git pull https://git.openjdk.org/jdk.git pull/19439/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 19439
View PR using the GUI difftool:
$ git pr show -t 19439
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/19439.diff
Webrev
Link to Webrev Comment