JDK-8286737 : Test vmTestbase/gc/gctests/WeakReference/weak006/weak006.java fails: Last soft reference has not been cleared
  • Type: Bug
  • Component: hotspot
  • Sub-Component: gc
  • Affected Version: 19
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2022-05-13
  • Updated: 2022-05-26
  • Resolved: 2022-05-26
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 19
19 masterFixed
Related Reports
Relates :  
Sub Tasks
JDK-8286782 :  
Description
This test has suddenly started failing on all platforms

Stress iterations factor: 1
Stress threads factor: 1
Stress runs factor: 1
Max memory: 1860698112
Sleep time: 500
Iterations: 0
Number of threads: 1
Run GC thread: false
Run mem diag thread: false
Run forever: false
Array size: 9624299
Starting Thread[#19,gc.gctests.WeakReference.weak006.weak006$Worker@68c54797,5,MainThreadGroup]
Exception in 
gc.gctests.WeakReference.weak006.weak006$Worker@68c54797
nsk.share.TestFailure: Last soft reference has not been cleared
	at gc.gctests.WeakReference.weak006.weak006$Worker.run(weak006.java:143)
	at nsk.share.runner.ThreadsRunner$ManagedThread.run(ThreadsRunner.java:128)
	at java.base/java.lang.Thread.run(Thread.java:1585)
Failures summary:
nsk.share.TestFailure: Last soft reference has not been cleared
	at gc.gctests.WeakReference.weak006.weak006$Worker.run(weak006.java:143)
	at nsk.share.runner.ThreadsRunner$ManagedThread.run(ThreadsRunner.java:128)
	at java.base/java.lang.Thread.run(Thread.java:1585)
----------System.err:(14/772)----------
nsk.share.TestFailure: Test exit code: 97
	at nsk.share.test.Tests$TestRunner.execute(Tests.java:90)
	at nsk.share.test.Tests$TestRunner.run(Tests.java:96)
	at nsk.share.gc.GC.runTest(GC.java:114)
	at gc.gctests.WeakReference.weak006.weak006.main(weak006.java:160)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at java.base/java.lang.reflect.Method.invoke(Method.java:578)
	at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:127)
	at java.base/java.lang.Thread.run(Thread.java:1585)

JavaTest Message: Test threw exception: nsk.share.TestFailure: Test exit code: 97
JavaTest Message: shutting down test
Comments
Changeset: 6a33974a Author: Leonid Mesnik <lmesnik@openjdk.org> Date: 2022-05-26 22:36:43 +0000 URL: https://git.openjdk.java.net/jdk/commit/6a33974a6b8a629744c6d76c3b4fa1f772e52ac8
26-05-2022

Comment from albertnetymk "Albert Yang": It was unclear to me why a Full GC cycle with the correct soft-ref policy couldn't discover/clear that soft ref, so I took a deeper look. My conclusion is that if a non-strong ref, A, is discovered in the Young GC cycle, it becomes live/reachable and its enclosing non-strong refs (if any) becomes non-discoverable in the Full GC cycle in the same pause. In contrast, that non-strong ref A is actually unreachable at the Java level, so the Full GC cycle can discover its enclosing non-strong refs. IOW, a pause including both Young and Full GC cycles can result in less reclaimed mem (or more kept objs) than a pause with only Full GC. Such behavior, IMO, is a bit counterintuitive. The fix of adding soft-ref policy to the Young GC doesn't resolve the general problem, because the young/old-gen and obj size could affect which generation various objs lie, which affects what non-strong refs will be discovered and treated as live. (The Weak ref case in the same test can also be triggered due to the same reason.) I believe one reliable solution here is to disable Full-GC-initiated Young GC using -XX:-ScavengeBeforeFullGC. (On my box I can confirm it fixes the failing test.)
24-05-2022

A pull request was submitted for review. URL: https://git.openjdk.java.net/jdk/pull/8829 Date: 2022-05-22 22:14:45 +0000
22-05-2022

The whitebox full gc ends up in VM_ParallelGCSystemGC; there parallel gc full gc is not told to do clear soft refs unconditionally: void VM_ParallelGCSystemGC::doit() { SvcGCMarker sgcm(SvcGCMarker::FULL); ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); GCCauseSetter gccs(heap, _gc_cause); if (!_full) { // If (and only if) the scavenge fails, this will invoke a full gc. heap->invoke_scavenge(); } else { heap->do_full_collection(false); // <--------------- } }
16-05-2022

The test always fails with ParallelGC. Need to check why WB.fullGC doesn't collect soft references.
15-05-2022

Looks like this was caused by JDK-8285951
13-05-2022