-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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
8287596: Reorg jdk.test.lib.util.ForceGC #8979
Conversation
👋 Welcome back xuelei! A progress list of the required criteria for merging this PR into |
@XueleiFan The following labels 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 lists. If you would like to change these labels, use the /label pull request command. |
Webrevs
|
JDK-8287384 causes I tried your patch and the test fails. |
I updated the waiting time back to 1 second. Would you please check again? |
1 similar comment
I updated the waiting time back to 1 second. Would you please check again? |
No, it doesn't work. You can build a fastdebug build with |
My macOS (M1) and Linux (CentOS) may be too powerful to reproduce the failure. I tried to set the JTREG time out to 60 seconds, and the timeout issue could be reproduced. In It looks like a regression introduced with the update for JDK-8287384. I did not fine the cause yet. I will have more checking tomorrow. |
@XueleiFan this pull request can not be integrated into git checkout JDK-8287596
git fetch https://git.openjdk.java.net/jdk master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push |
* if did not complete after 10 Seconds | ||
*/ | ||
public static boolean wait(BooleanSupplier booleanSupplier) { | ||
return wait(booleanSupplier, 10000L); |
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.
For the max waiting time, instead of a fixed value I strongly recommend choosing some base waiting time, say 1 second, and scaling it by the jtreg timeout factor.
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 also have similar feedback. The timeout factor can be found in the test.timeout.factor
system property, if present. When running tests with -Xcomp in a fastdebug build, the timeout factor is currently configured to 10. Setting the base waiting time to 1 second seems reasonable.
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.
Good point! I changed to use 1 second as the base waiting time. I was not very sure if 1 second is big enough for the GC cleanup, but the testing result on my laptop and VMs, which are super fast, looks good to me. Please help to check mach5 result.
throw new RuntimeException("loader " + " not unloaded!"); | ||
} | ||
} | ||
|
||
boolean tryUnload() { | ||
ForceGC gc = new ForceGC(); | ||
return gc.await(() -> weakRef.get() == null); | ||
return ForceGC.wait(() -> weakRef.get() == null, 1000L); |
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 verifies that the reference will never become weakly unreachable, i.e. it remains strongly reachable.
I suggest to add a method default to 200ms (?) timeout scaled with the timeout factor and expect the specified condition will never met. Maybe call it ForceGC.neverTrue(BooleanSupplier)
? Need to tune the base waiting time; for example if timeout factor is 4, then total wait would be 800 ms.
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 see your points.
When I changed the waiting time to 1 second scaled with timeout factor, it looks like safe to use the ForceGC.wait() method for either cleanup and non-cleanup checking. The default JTREG timeout for a test case is 120 seconds. 1 seconds may be small enough so that we could use it for both cases.
@@ -61,8 +61,7 @@ public void testClassLoaderLeak() throws Exception { | |||
con = null; | |||
assertNotNull(myOwnClassLoaderWeakReference.get()); | |||
|
|||
ForceGC gc = new ForceGC(); | |||
assertTrue(gc.await(() -> myOwnClassLoaderWeakReference.get() == null)); | |||
assertTrue(ForceGC.wait(() -> myOwnClassLoaderWeakReference.get() == null)); |
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 call to ref.get() can create a strong reference to the object; depending on the timing it might interfere with the GC in process.
ref.refersTo(null)
is preferred over ref.get() == null
Here and all subsequent changes.
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.
Good point. I learned a lot these days from PRs comments! Thank you!
The patch is changed to use refersTo().
ping ... |
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.
Sorry for the delay.
} | ||
// The jtreg testing timeout factor. | ||
private static final double TIMEOUT_FACTOR = Double.valueOf( | ||
System.getProperty("test.timeout.factor", "1.0")); |
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.
If you don't mind the dependency, you can use jdk.test.lib.Utils.TIMEOUT_FACTOR
or Utils.adjustTimeout(xx)
in the usage below.
* unless the thread is interrupted or a predefined waiting time elapses. | ||
* Causes the current thread to wait until the {@code booleanSupplier} | ||
* returns true, or a specific waiting time elapses. The waiting time | ||
* is 1 second scalled with the jtreg testing timeout factor. |
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.
typo: "scalled" -> "scaled"
Reference.reachabilityFence(obj); | ||
Reference.reachabilityFence(ref); | ||
|
||
for (int retries = (int)(timeout / 200); retries >= 0; retries--) { |
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 logic around the timeout might be clearer if it was only based on the number of retries,
and can be scaled by the TIMEOUT_FACTOR 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.
I just curious if the factor could be set to some unusual values like "1.25". Scaling on timeout, and then calculating the retires could be more accuracy for such circumstances, although it may be not necessary. I moved the retries calculation close to the for-loop. Hope it is better for readers.
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.
Yes, Utils.adjustTimeout(long x)
uses floating point and then converts back.
// if the reference has already been removed from the queue. | ||
// But it is fine. For most cases, the 1st GC is sufficient | ||
// to trigger and complete the cleanup. | ||
queue.remove(200L); |
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.
If remove()
returns a non-null value, then it is safe to break out of the loop.
The GC has cleared the ref. And the final getAsBoolean()
below will return the condition.
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'm not sure if all unused object will be collected in one GC call always. The gc() specification says "When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all unused objects. ... There is also no guarantee that this effort will determine the change of reachability in any particular number of objects, or that any particular number of {@link java.lang.ref.Reference Reference} objects will be cleared and enqueued." But from the spec, I did not get a clear answer for the question.
If the booleanSupplier
object could be cleared in a collection other than the ref
collection, the current code may be safer.
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.
True, knowing when GC is 'done' is not deterministic except for a specify Reference to a specific object.
System.gc is just a request, the checking for an object can more quickly exit the loop.
The code is as is, and already commented, might wait an extra cycle, but only in the case of a race between the requested predicate and the object being reclaimed. Ok as it.
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.
Maybe not for this PR - but it could be useful to have a version of ForceGC that takes as parameter a ReferenceQueue<T>
and a Reference<T>
. That would be more efficient than creating a new object and waiting for a different cleaner thread to cleanup that object.
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.
@dfuch Taking a reference as parameter could simplify the use of ForceGC. I though about this idea as well, when I had to check lambada expressions in each call. I would like to do it in the future so that this PR could focus on less things.
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.
Thanks @XueleiFan, that's fine by me!
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.
When using Reference/ReferenceQueue there is no Cleaner, only normal reference processing (via GC).
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 have tests that use Reference/ReferenceQueue to check that an object that uses a Cleaner has been garbage collected. I don't use ForceGC in those tests because it's much more efficient to wait on my ReferenceQueue rather than having ForceGC wait on something else.
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
@XueleiFan 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 no new commits pushed to the ➡️ To integrate this PR with the above commit message to the |
Could someone in Oracle help me run Mach 5 testing? |
Does this address JDK-8288286 and allow ReflectionCallerCacheTest.java to be removed from ProblemList-Xcomp.txt? |
|
Thanks a lot! |
I think JDK-8288286 should be addressed, but I would like to have it further evaluated via more Mach5 testing before remove the case from problem list. |
/integrate |
Going to push as commit 82a8bd7.
Your commit was automatically rebased without conflicts. |
@XueleiFan Pushed as commit 82a8bd7. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
This is a follow up update per comments in JDK-8287384 PR. The tier1 and tier2 test in open part looks good to me. Please help to run Mach5 just case the closed test cases are impacted.
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/8979/head:pull/8979
$ git checkout pull/8979
Update a local copy of the PR:
$ git checkout pull/8979
$ git pull https://git.openjdk.org/jdk pull/8979/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 8979
View PR using the GUI difftool:
$ git pr show -t 8979
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/8979.diff