From d185a6c53e2a1dbf7aca47c431baa8df6ee1ca8b Mon Sep 17 00:00:00 2001 From: Attila Szegedi Date: Tue, 2 Mar 2021 12:25:25 +0000 Subject: [PATCH] 8261483: jdk/dynalink/TypeConverterFactoryMemoryLeakTest.java failed with "AssertionError: Should have GCd a method handle by now" Reviewed-by: shade, plevart --- test/jdk/ProblemList.txt | 2 - .../TypeConverterFactoryMemoryLeakTest.java | 50 ++++++++++++++--- .../TypeConverterFactoryRetentionTests.java | 55 +++++++++++++++---- 3 files changed, 84 insertions(+), 23 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index c017cc9eea3..4ce94df4d1b 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -817,8 +817,6 @@ javax/rmi/ssl/SSLSocketParametersTest.sh 8162906 generic- javax/script/Test7.java 8239361 generic-all -jdk/dynalink/TypeConverterFactoryMemoryLeakTest.java 8261483 generic-all - ############################################################################ # jdk_jfr diff --git a/test/jdk/jdk/dynalink/TypeConverterFactoryMemoryLeakTest.java b/test/jdk/jdk/dynalink/TypeConverterFactoryMemoryLeakTest.java index 8fa48569db2..4735bb4a08f 100644 --- a/test/jdk/jdk/dynalink/TypeConverterFactoryMemoryLeakTest.java +++ b/test/jdk/jdk/dynalink/TypeConverterFactoryMemoryLeakTest.java @@ -22,10 +22,43 @@ */ /* - * @test + * @test id=with_SerialGC + * @requires vm.gc.Serial * @bug 8198540 - * @summary Test TypeConverterFactory is not leaking method handles - * @author Attila Szegedi + * @summary Test TypeConverterFactory is not leaking method handles (Serial GC) + * @run main/othervm -XX:+UseSerialGC TypeConverterFactoryMemoryLeakTest + */ + +/* + * @test id=with_ParallelGC + * @requires vm.gc.Parallel + * @bug 8198540 + * @summary Test TypeConverterFactory is not leaking method handles (Parallel GC) + * @run main/othervm -XX:+UseParallelGC TypeConverterFactoryMemoryLeakTest + */ + +/* + * @test id=with_G1GC + * @requires vm.gc.G1 + * @bug 8198540 + * @summary Test TypeConverterFactory is not leaking method handles (G1 GC) + * @run main/othervm -XX:+UseG1GC TypeConverterFactoryMemoryLeakTest + */ + +/* + * @test id=with_ZGC + * @requires vm.gc.Z + * @bug 8198540 + * @summary Test TypeConverterFactory is not leaking method handles (Z GC) + * @run main/othervm -XX:+UseZGC TypeConverterFactoryMemoryLeakTest + */ + +/* + * @test id=with_ShenandoahGC + * @requires vm.gc.Shenandoah + * @bug 8198540 + * @summary Test TypeConverterFactory is not leaking method handles (Shenandoah GC) + * @run main/othervm -XX:+UseShenandoahGC TypeConverterFactoryMemoryLeakTest */ import java.lang.invoke.MethodHandles; @@ -34,7 +67,6 @@ import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; -import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; @@ -52,8 +84,9 @@ * becomes unreachable. */ public class TypeConverterFactoryMemoryLeakTest { - // Usually succeeds in less than a second, but give it time - private static final Duration MAX_DURATION = Duration.ofSeconds(15); + // With explicit GC calls succeeds in 11-12 iterations depending on GC used. + // 1000 should be a safe upper limit after which we can consider it failed. + private static final int MAX_ITERATIONS = 1000; private static final ReferenceQueue refQueue = new ReferenceQueue<>(); private static final List> refs = new ArrayList<>(); @@ -74,11 +107,10 @@ public GuardedInvocation convertToType(Class sourceType, Class targetType, } public static void main(String[] args) { - long start = System.nanoTime(); - long deadline = start + MAX_DURATION.toNanos(); - while (System.nanoTime() < deadline) { + for (int count = 0; count < MAX_ITERATIONS; count++) { // Just create them as fast as possible without retaining. makeOne(); + System.gc(); if (refQueue.poll() != null) { // Success, a method handle became phantom reachable. return; diff --git a/test/jdk/jdk/dynalink/TypeConverterFactoryRetentionTests.java b/test/jdk/jdk/dynalink/TypeConverterFactoryRetentionTests.java index 3c4fcbfc0ec..8ad972d4502 100644 --- a/test/jdk/jdk/dynalink/TypeConverterFactoryRetentionTests.java +++ b/test/jdk/jdk/dynalink/TypeConverterFactoryRetentionTests.java @@ -22,10 +22,43 @@ */ /* - * @test + * @test id=with_SerialGC + * @requires vm.gc.Serial * @bug 8198540 - * @summary Test TypeConverterFactory is not leaking class loaders - * @author Attila Szegedi + * @summary Test TypeConverterFactory is not leaking class loaders (Serial GC) + * @run main/othervm -XX:+UseSerialGC TypeConverterFactoryRetentionTests + */ + +/* + * @test id=with_ParallelGC + * @requires vm.gc.Parallel + * @bug 8198540 + * @summary Test TypeConverterFactory is not leaking class loaders (Parallel GC) + * @run main/othervm -XX:+UseParallelGC TypeConverterFactoryRetentionTests + */ + +/* + * @test id=with_G1GC + * @requires vm.gc.G1 + * @bug 8198540 + * @summary Test TypeConverterFactory is not leaking class loaders (G1 GC) + * @run main/othervm -XX:+UseG1GC TypeConverterFactoryRetentionTests + */ + +/* + * @test id=with_ZGC + * @requires vm.gc.Z + * @bug 8198540 + * @summary Test TypeConverterFactory is not leaking class loaders (Z GC) + * @run main/othervm -XX:+UseZGC TypeConverterFactoryRetentionTests + */ + +/* + * @test id=with_ShenandoahGC + * @requires vm.gc.Shenandoah + * @bug 8198540 + * @summary Test TypeConverterFactory is not leaking class loaders (Shenandoah GC) + * @run main/othervm -XX:+UseShenandoahGC TypeConverterFactoryRetentionTests */ import java.lang.invoke.MethodHandle; @@ -33,7 +66,6 @@ import java.lang.invoke.MethodType; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; -import java.time.Duration; import java.util.ArrayList; import java.util.Base64; import java.util.List; @@ -50,8 +82,9 @@ * from getting garbage collected. */ public class TypeConverterFactoryRetentionTests { - // Usually succeeds in less than a second, but give it time - private static final Duration MAX_DURATION = Duration.ofSeconds(15); + // With explicit GC calls succeeds in 1-2 iterations depending on GC used. + // 1000 should be a safe upper limit after which we can consider it failed. + private static final int MAX_ITERATIONS = 1000; private static class TestLinker implements GuardingDynamicLinker, GuardingTypeConverterFactory { public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) { @@ -134,15 +167,14 @@ private static void testFromOneClassToClassLoader(Class y) throws ClassNotFou LinkerServices linkerServices = createLinkerServices(); - long start = System.nanoTime(); - long deadline = start + MAX_DURATION.toNanos(); - while (System.nanoTime() < deadline) { + for (int count = 0; count < MAX_ITERATIONS; count++) { TestClassLoader cl = new TestClassLoader(y.getClassLoader(), "X"); Class x = Class.forName("X", true, cl); assert x.getClassLoader() == cl; linkerServices.getTypeConverter(y, x); linkerServices.getTypeConverter(x, y); refs.add(new PhantomReference<>(cl, refQueue)); + System.gc(); if (refQueue.poll() != null) { return; } @@ -165,9 +197,7 @@ private static void testUnrelatedLoaders() throws ClassNotFoundException { LinkerServices linkerServices = createLinkerServices(); - long start = System.nanoTime(); - long deadline = start + MAX_DURATION.toNanos(); - while (System.nanoTime() < deadline) { + for (int count = 0; count < MAX_ITERATIONS; count++) { TestClassLoader cl1 = new TestClassLoader(null, "X"); Class x = Class.forName("X", true, cl1); assert x.getClassLoader() == cl1; @@ -178,6 +208,7 @@ private static void testUnrelatedLoaders() throws ClassNotFoundException { linkerServices.getTypeConverter(x, y); refs.add(new PhantomReference<>(cl1, refQueue1)); refs.add(new PhantomReference<>(cl2, refQueue2)); + System.gc(); if (refQueue1.poll() != null) { gc1 = true; }