Path: blob/jdk8u272-b10-aarch32-20201026/jdk/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java
48795 views
/*1* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test LFGarbageCollectedTest25* @bug 804670326* @ignore 807860227* @summary Test verifies that lambda forms are garbage collected28* @author kshefov29* @library /lib/testlibrary/jsr292 /lib/testlibrary30* @build TestMethods31* @build LambdaFormTestCase32* @build LFGarbageCollectedTest33* @run main/othervm -Xmx64m -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+HeapDumpOnOutOfMemoryError -DHEAP_DUMP=false LFGarbageCollectedTest34*/3536import java.lang.invoke.MethodHandle;37import java.lang.invoke.MethodType;38import java.lang.ref.PhantomReference;39import java.lang.ref.Reference;40import java.lang.ref.ReferenceQueue;41import java.lang.reflect.InvocationTargetException;42import java.util.EnumSet;43import java.util.Map;4445/**46* Lambda forms garbage collection test class.47*/48public final class LFGarbageCollectedTest extends LambdaFormTestCase {49private static boolean HEAP_DUMP = Boolean.getBoolean("HEAP_DUMP");5051/**52* Constructor for a lambda forms garbage collection test case.53*54* @param testMethod A method from {@code j.l.i.MethodHandles} class that55* returns a {@code j.l.i.MethodHandle} instance.56*/57public LFGarbageCollectedTest(TestMethods testMethod) {58super(testMethod);59}6061PhantomReference ph;62ReferenceQueue rq = new ReferenceQueue();63MethodType mtype;64Map<String, Object> data;6566@Override67public void doTest() {68try {69TestMethods testCase = getTestMethod();70data = testCase.getTestCaseData();71MethodHandle adapter;72try {73adapter = testCase.getTestCaseMH(data, TestMethods.Kind.ONE);74} catch (NoSuchMethodException ex) {75throw new Error("Unexpected exception", ex);76}77mtype = adapter.type();78Object lambdaForm = INTERNAL_FORM.invoke(adapter);79if (lambdaForm == null) {80throw new Error("Unexpected error: Lambda form of the method handle is null");81}8283String debugName = (String)DEBUG_NAME.get(lambdaForm);84if (debugName != null && debugName.startsWith("identity_")) {85// Ignore identity_* LambdaForms.86return;87}8889ph = new PhantomReference(lambdaForm, rq);90lambdaForm = null;91adapter = null;9293collectLambdaForm();94} catch (IllegalAccessException | IllegalArgumentException |95InvocationTargetException ex) {96throw new Error("Unexpected exception", ex);97}98}99100private void collectLambdaForm() throws IllegalAccessException {101// Usually, 2 System.GCs are necessary to enqueue a SoftReference.102System.gc();103System.gc();104105Reference ref = null;106for (int i = 0; i < 10; i++) {107try {108ref = rq.remove(1000);109} catch (InterruptedException e) {110/* ignore */111}112if (ref != null) {113break;114}115System.gc(); // If the reference hasn't been queued yet, trigger one more GC.116}117118if (ref == null) {119dumpTestData();120System.err.println("Method type: " + mtype);121System.err.println("LambdaForm: " + REF_FIELD.get(ph));122123if (HEAP_DUMP) {124// Trigger OOM to force heap dump for post-mortem analysis.125val = new long[1_000_000_000];126}127throw new AssertionError("Error: LambdaForm is not garbage collected");128};129}130131private void dumpTestData() {132System.err.println("Test case: " + getTestMethod());133for (String s : data.keySet()) {134System.err.printf("\t%20s => %s\n", s, data.get(s));135}136}137138private static long[] val;139140/**141* Main routine for lambda forms garbage collection test.142*143* @param args Accepts no arguments.144*/145public static void main(String[] args) {146// The "identity", "constant", "arrayElementGetter" and "arrayElementSetter"147// methods should be removed from this test,148// because their lambda forms are stored in a static field and are not GC'ed.149// There can be only a finite number of such LFs for each method,150// so no memory leak happens.151EnumSet<TestMethods> testMethods = EnumSet.complementOf(EnumSet.of(152TestMethods.IDENTITY,153TestMethods.CONSTANT,154TestMethods.ARRAY_ELEMENT_GETTER,155TestMethods.ARRAY_ELEMENT_SETTER,156TestMethods.EXACT_INVOKER,157TestMethods.INVOKER));158LambdaFormTestCase.runTests(LFGarbageCollectedTest::new, testMethods);159}160}161162163