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 * @ignore 8057020
30 * @library /lib/testlibrary/jsr292 /lib/testlibrary
31 * @build TestMethods
32 * @build LambdaFormTestCase
33 * @build LFGarbageCollectedTest
34 * @run main/othervm LFGarbageCollectedTest
35 */
36
37 import java.lang.invoke.MethodHandle;
38 import java.lang.ref.PhantomReference;
39 import java.lang.ref.ReferenceQueue;
40 import java.lang.reflect.InvocationTargetException;
41 import java.util.EnumSet;
42 import java.util.Map;
43
44 /**
45 * Lambda forms garbage collection test class.
46 */
47 public 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", "constant", "arrayElementGetter" and "arrayElementSetter"
97 // methods should be removed from this test,
98 // because their lambda forms are stored in a static field and are not GC'ed.
99 // There can be only a finite number of such LFs for each method,
100 // so no memory leak happens.
101 EnumSet<TestMethods> testMethods = EnumSet.complementOf(EnumSet.of(
102 TestMethods.IDENTITY,
103 TestMethods.CONSTANT,
104 TestMethods.ARRAY_ELEMENT_GETTER,
105 TestMethods.ARRAY_ELEMENT_SETTER));
106 LambdaFormTestCase.runTests(LFGarbageCollectedTest::new, testMethods);
107 }
108 }
|
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 -Xmx64m -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+HeapDumpOnOutOfMemoryError -DHEAP_DUMP=false LFGarbageCollectedTest
34 */
35
36 import java.lang.invoke.MethodHandle;
37 import java.lang.invoke.MethodType;
38 import java.lang.ref.PhantomReference;
39 import java.lang.ref.Reference;
40 import java.lang.ref.ReferenceQueue;
41 import java.lang.reflect.Field;
42 import java.lang.reflect.InvocationTargetException;
43 import java.util.EnumSet;
44 import java.util.Map;
45
46 /**
47 * Lambda forms garbage collection test class.
48 */
49 public final class LFGarbageCollectedTest extends LambdaFormTestCase {
50 private static boolean HEAP_DUMP = Boolean.getBoolean("HEAP_DUMP");
51
52 /**
53 * Constructor for a lambda forms garbage collection test case.
54 *
55 * @param testMethod A method from {@code j.l.i.MethodHandles} class that
56 * returns a {@code j.l.i.MethodHandle} instance.
57 */
58 public LFGarbageCollectedTest(TestMethods testMethod) {
59 super(testMethod);
60 }
61
62 PhantomReference ph;
63 ReferenceQueue rq = new ReferenceQueue();
64 MethodType mtype;
65 Map<String, Object> data;
66
67 @Override
68 public void doTest() {
69 try {
70 TestMethods testCase = getTestMethod();
71 if (testCase == TestMethods.EXACT_INVOKER || testCase == TestMethods.INVOKER) {
72 // Invokers aren't collected.
73 return;
74 }
75 data = testCase.getTestCaseData();
76 MethodHandle adapter;
77 try {
78 adapter = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE);
79 } catch (NoSuchMethodException ex) {
80 throw new Error("Unexpected exception: ", ex);
81 }
82 mtype = adapter.type();
83 if (mtype.parameterCount() == 0) {
84 // Ignore identity_* LambdaForms.
85 return;
86 }
87 Object lambdaForm = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter);
88 if (lambdaForm == null) {
89 throw new Error("Unexpected error: Lambda form of the method handle is null");
90 }
91 ph = new PhantomReference(lambdaForm, rq);
92 lambdaForm = null;
93 adapter = null;
94
95 collectLambdaForm();
96 } catch (IllegalAccessException | IllegalArgumentException |
97 InvocationTargetException ex) {
98 throw new Error("Unexpected exception: ", ex);
99 }
100 }
101
102
103 private void collectLambdaForm() throws IllegalAccessException {
104 // Usually, 2 System.GCs are necessary to enqueue a SoftReference.
105 System.gc();
106 System.gc();
107
108 Reference ref = null;
109 for (int i = 0; i < 10; i++) {
110 try {
111 ref = rq.remove(1000);
112 } catch (InterruptedException e) {
113 /* ignore */
114 }
115 if (ref != null) {
116 break;
117 }
118 System.gc(); // If the reference hasn't been queued yet, trigger one more GC.
119 }
120
121 if (ref == null) {
122 dumpTestData();
123 System.err.println("Method type: " + mtype);
124 System.err.println("LambdaForm: " + REF_FIELD.get(ph));
125
126 if (HEAP_DUMP) {
127 // Trigger OOM to force heap dump for post-mortem analysis.
128 val = new long[1_000_000_000];
129 }
130 throw new AssertionError("Error: LambdaForm is not garbage collected");
131 };
132 }
133
134 private void dumpTestData() {
135 System.err.println("Test case: " + getTestMethod());
136 for (String s : data.keySet()) {
137 System.err.printf("\t%20s => %s\n", s, data.get(s));
138 }
139 }
140
141 private static long[] val;
142 private static final Field REF_FIELD;
143 static {
144 try {
145 REF_FIELD = Reference.class.getDeclaredField("referent");
146 REF_FIELD.setAccessible(true);
147 } catch (Exception e) {
148 throw new Error(e);
149 }
150 }
151
152 /**
153 * Main routine for lambda forms garbage collection test.
154 *
155 * @param args Accepts no arguments.
156 */
157 public static void main(String[] args) {
158 // The "identity", "constant", "arrayElementGetter" and "arrayElementSetter"
159 // methods should be removed from this test,
160 // because their lambda forms are stored in a static field and are not GC'ed.
161 // There can be only a finite number of such LFs for each method,
162 // so no memory leak happens.
163 EnumSet<TestMethods> testMethods = EnumSet.complementOf(EnumSet.of(
164 TestMethods.IDENTITY,
165 TestMethods.CONSTANT,
166 TestMethods.ARRAY_ELEMENT_GETTER,
167 TestMethods.ARRAY_ELEMENT_SETTER));
168 LambdaFormTestCase.runTests(LFGarbageCollectedTest::new, testMethods);
169 }
170 }
|