RFR: 8283276: java/io/ObjectStreamClass/ObjectStreamClassCaching.java fails with various GCs
Peter Levart
plevart at openjdk.org
Mon Jul 25 13:27:56 UTC 2022
On Mon, 18 Jul 2022 07:40:53 GMT, Aleksey Shipilev <shade at openjdk.org> wrote:
> Test appears to pass fine with G1. But it fails with other GCs, for example Parallel, Shenandoah, etc, it fails:
>
>
> $ CONF=linux-x86_64-server-fastdebug make test TEST=java/io/ObjectStreamClass/ObjectStreamClassCaching.java TEST_VM_OPTS="-XX:+UseParallelGC"
>
> test ObjectStreamClassCaching.testCacheReleaseUnderMemoryPressure(): success
> test ObjectStreamClassCaching.testCachingEffectiveness(): failure
> java.lang.AssertionError: Cache lost entry although memory was not under pressure expected [false] but found [true]
> at org.testng.Assert.fail(Assert.java:99)
> at org.testng.Assert.failNotEquals(Assert.java:1037)
> at org.testng.Assert.assertFalse(Assert.java:67)
>
>
> I believe this is because `System.gc()` is not that reliable about what happens with weak references. As seen with other GCs, they can clear the weakrefs on Full GC. In fact, the test fails with G1 if we do a second System.gc() in this test. So the test itself is flaky. The fix is to avoid doing `System.gc()` altogether in that subtest. The test is still retained to see that reference is not cleared for a while.
>
> Additional testing:
> - [x] Linux x86_64 fastdebug, affected test with `-XX:+UseSerialGC`, 100 repetitions
> - [x] Linux x86_64 fastdebug, affected test with `-XX:+UseParallelGC`, 100 repetitions
> - [x] Linux x86_64 fastdebug, affected test with `-XX:+UseG1GC`, 100 repetitions
> - [x] Linux x86_64 fastdebug, affected test with `-XX:+UseShenandoahGC`, 100 repetitions
> - [x] Linux x86_64 fastdebug, affected test with `-XX:+UseZGC`, 100 repetitions
...my above claims might appear strange to some reader as the test clearly wraps a cached ObjectStreamClass instance with a WeakReference and then checks whether this WeakReference is cleared or not. So an explanation is in order... The internal cache uses SoftReference(s). Since the cache is encapsulated, the test does not check it directly but uses a trick. It wraps the cached instance with a WeakReference. Since the instance is already wrapped with SoftReference in the cache and there is no strong reference holding it, the instance can be considered Softly Reachable. And we know that GC must clear all XxxReference(s) regardless of their type pointing to the same referent atomically. By detecting in the test that a WeakReference is cleared, we assume that the internal SoftReference is cleared too. If this was not the case, GC could be considdered to have a bug and is not by the spec. So what we are observing now is either System.gc() clearing SoftReference or a GC bug. I don't bel
ive it is a GC bug though.
-------------
PR: https://git.openjdk.org/jdk/pull/9533
More information about the core-libs-dev
mailing list