Skip to content
This repository has been archived by the owner on Aug 27, 2022. It is now read-only.

Commit

Permalink
8261483: jdk/dynalink/TypeConverterFactoryMemoryLeakTest.java failed …
Browse files Browse the repository at this point in the history
…with "AssertionError: Should have GCd a method handle by now"

Reviewed-by: shade, plevart
  • Loading branch information
szegedi committed Mar 2, 2021
1 parent 85a5ae8 commit d185a6c
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 23 deletions.
2 changes: 0 additions & 2 deletions test/jdk/ProblemList.txt
Expand Up @@ -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
Expand Down
50 changes: 41 additions & 9 deletions test/jdk/jdk/dynalink/TypeConverterFactoryMemoryLeakTest.java
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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<MethodHandle> refQueue = new ReferenceQueue<>();
private static final List<Reference<MethodHandle>> refs = new ArrayList<>();
Expand All @@ -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;
Expand Down
55 changes: 43 additions & 12 deletions test/jdk/jdk/dynalink/TypeConverterFactoryRetentionTests.java
Expand Up @@ -22,18 +22,50 @@
*/

/*
* @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;
import java.lang.invoke.MethodHandles;
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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down

0 comments on commit d185a6c

Please sign in to comment.