LFGarbageCollectedTest.java revision 10652:cabbfab50bd9
1/*
2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test LFGarbageCollectedTest
26 * @bug 8046703
27 * @summary Test verifies that lambda forms are garbage collected
28 * @author kshefov
29 * @library /lib/testlibrary/jsr292 /lib/testlibrary
30 * @build TestMethods
31 * @build LambdaFormTestCase
32 * @build LFGarbageCollectedTest
33 * @run main/othervm/timeout=600 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true -DtestLimit=150 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI LFGarbageCollectedTest
34 */
35
36import java.lang.invoke.MethodHandle;
37import java.lang.ref.PhantomReference;
38import java.lang.ref.ReferenceQueue;
39import java.lang.reflect.InvocationTargetException;
40import java.util.Arrays;
41import java.util.EnumSet;
42import java.util.Map;
43
44/**
45 * Lambda forms garbage collection test class.
46 */
47public final class LFGarbageCollectedTest extends LambdaFormTestCase {
48
49    /**
50     * Constructor for a lambda forms garbage collection test case.
51     *
52     * @param testMethod A method from {@code j.l.i.MethodHandles} class that
53     * returns a {@code j.l.i.MethodHandle} instance.
54     */
55    public LFGarbageCollectedTest(TestMethods testMethod) {
56        super(testMethod);
57    }
58
59    @Override
60    public void doTest() {
61        try {
62            Map<String, Object> data = getTestMethod().getTestCaseData();
63            MethodHandle adapter;
64            try {
65                adapter = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE);
66            } catch (NoSuchMethodException ex) {
67                throw new Error("Unexpected exception: ", ex);
68            }
69            Object lambdaForm = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter);
70            if (lambdaForm == null) {
71                throw new Error("Unexpected error: Lambda form of the method handle is null");
72            }
73            ReferenceQueue rq = new ReferenceQueue();
74            PhantomReference ph = new PhantomReference(lambdaForm, rq);
75            lambdaForm = null;
76            data = null;
77            adapter = null;
78            for (int i = 0; i < 1000 && !ph.isEnqueued(); i++) {
79                System.gc();
80            }
81            if (!ph.isEnqueued()) {
82                throw new AssertionError("Error: Lambda form is not garbage collected");
83            }
84        } catch (IllegalAccessException | IllegalArgumentException |
85                InvocationTargetException ex) {
86            throw new Error("Unexpected exception: ", ex);
87        }
88    }
89
90    /**
91     * Main routine for lambda forms garbage collection test.
92     *
93     * @param args Accepts no arguments.
94     */
95    public static void main(String[] args) {
96        // The "identity" and "constant" methods should be removed from this test,
97        // because their lambda forms are stored in a static filed and are not GC'ed.
98        // There can be only 5 such LFs for each method, so no memory leak happens.
99        EnumSet<TestMethods> testMethods = EnumSet.complementOf(EnumSet.of(TestMethods.IDENTITY, TestMethods.CONSTANT));
100        LambdaFormTestCase.runTests(LFGarbageCollectedTest::new, testMethods);
101    }
102}
103