Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.
/ jdk13u-dev Public archive

8261483: jdk/dynalink/TypeConverterFactoryMemoryLeakTest.java failed with "AssertionError: Should have GCd a method handle by now" #136

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions test/jdk/TEST.ROOT
Original file line number Diff line number Diff line change
@@ -44,6 +44,9 @@ requires.extraPropDefns.vmOpts = -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
requires.properties= \
sun.arch.data.model \
java.runtime.name \
vm.gc.Serial \
vm.gc.Parallel \
vm.gc.G1 \
vm.gc.Z \
vm.gc.Shenandoah \
vm.graal.enabled \
50 changes: 41 additions & 9 deletions test/jdk/jdk/dynalink/TypeConverterFactoryMemoryLeakTest.java
Original file line number Diff line number Diff line change
@@ -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:+UnlockExperimentalVMOptions -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<MethodHandle> refQueue = new ReferenceQueue<>();
private static final List<Reference<MethodHandle>> 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;
55 changes: 43 additions & 12 deletions test/jdk/jdk/dynalink/TypeConverterFactoryRetentionTests.java
Original file line number Diff line number Diff line change
@@ -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:+UnlockExperimentalVMOptions -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;
@@ -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;
}