-
Notifications
You must be signed in to change notification settings - Fork 5.8k
8176567: nsk/jdi/ReferenceType/instances/instances002: TestFailure: Unexpected size of referenceType.instances(nsk.share.jdi.TestInterfaceImplementer1): 11, expected: 10 #6943
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
👋 Welcome back cjplummer! A progress list of the required criteria for merging this PR into |
@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
|
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 fix looks good to me. Nice analysis!
Thanks,
Serguei
@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 205 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 |
/integrate |
Going to push as commit 46fd683.
Your commit was automatically rebased without conflicts. |
@plummercj Pushed as commit 46fd683. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
The test is failing because it is detecting an extra instance of
TestClass1
. The test (the debugger side) first tells the debuggee to create 10 instances ofTestClass1
. The debugger then uses JDIClassType.newInstance()
to create 100 more instances. It then resumes the debuggee and usesRefrenceType.instances()
to find out how many instances ofTestClass1
are reachable. Since the 100 created byClassType.newInstance()
should not have any references keeping them live, the answer should be 10, but sometimes it ends up being 11, so there is an extra instance.I determined that this extra instance is always the last of the 100 that are created with
ClassType.newInstance()
. It uses the JDI/JDWP invoker interface. I found the following code in the debug agent invoker.c to be the problem:The first block is responsible for sending the reply to the debugger for the JDI
ClassType.newInstance()
call.returnValue
is a JNI global ref to the object that was just created, andtossGlobalRef()
frees it after the reply packet has been sent. The problem is that once the reply packet has been received by the debugger (for the 100thTestClass1
allocation), it resumes the debuggee and issues theReferenceType.instances()
call. This might be handled by the debug agent before it ever gets to thetossGlobalRef()
call. So there will still be a reference to the 100thTestClass1
object.The fix is to call
tossGlobalRef()
after we are done withreturnValue
, but before sending out the packet. We are done withreturnValue
once theoutStream_writeValue()
call has been made. I decided to handleexc
(the exception object) in the same manner. Although no tests were failing as a result of releasing it after sending the reply, I think you could write a test that triggered an exception and verified that the exception was not still considered live after doing the resume.Regarding any concerns you might have for moving
tossGlobalRef()
code from outside theif (!detached)
to inside, if you follow the logic of this function you'll see thatmustReleaseReturnValue
can only be set true ifdetached
is false. You'll also see thatexc
can only be non-null ifdetached
is false. Thus these twotossGlobalRef()
calls were only ever made whendetached
was false, and that remains true after my changes.Regarding any concerns you might have for making the
tossGlobalRef()
calls outside of the locks, the locking is a remnant from when theexception
andreturnValue
fields were referenced directly out of theInvokeRequest
struct, which could be accessed by other threads. That is no longer the case after changes were made for JDK-8181419, which copied the fields into local variables. This code actually has been subject to a pretty long bug tail. See the last couple of long comments by me in JDK-8176567 for details.Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/6943/head:pull/6943
$ git checkout pull/6943
Update a local copy of the PR:
$ git checkout pull/6943
$ git pull https://git.openjdk.java.net/jdk pull/6943/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 6943
View PR using the GUI difftool:
$ git pr show -t 6943
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/6943.diff