/* * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.LinkedList; import java.util.ListIterator; /* * @test * @requires vm.gc.ConcMarkSweep * @key cte_test * @bug 4950157 * @summary Stress the behavior of ergonomics when the heap is nearly full and * stays nearly full. * @run main/othervm * -XX:+UseConcMarkSweepGC -XX:-CMSYield -XX:-CMSPrecleanRefLists1 * -XX:CMSInitiatingOccupancyFraction=0 -Xmx80m TestBubbleUpRef 16000 50 10000 */ /** * Test program to stress the behavior of ergonomics when the * heap is nearly full and stays nearly full. * This is a test to catch references that have been discovered * during concurrent marking and whose referents have been * cleared by the mutator. * Allocate objects with weak references until the heap is full * Free the objects. * Do work so that concurrent marking has a chance to work * Clear the referents out of the weak references * System.gc() in the hopes that it will acquire the collection * Free the weak references * Do it again. * * Use the following VM options * -Xmx80m -XX:-CMSYield [-XX:+UseConcMarkSweepGC] -XX:-CMSPrecleanRefLists1 * -XX:CMSInitiatingOccupancyFraction=0 * * Use parameter: * args[0] - array size (16000) * args[1] - iterations (50) * args[2] - work (10000) */ class MyList extends LinkedList { int[] a; MyList(int size) { a = new int[size]; } } class MyRefList extends LinkedList { WeakReference ref; MyRefList(Object o, ReferenceQueue rq) { ref = new WeakReference(o, rq); } void clearReferent() { ref.clear(); } } public class TestBubbleUpRef { MyList list; MyRefList refList; ReferenceQueue rq; int refListLen; int arraySize; int iterations; int workUnits; TestBubbleUpRef(int as, int cnt, int wk) { arraySize = as; iterations = cnt; workUnits = wk; list = new MyList(arraySize); refList = new MyRefList(list, rq); } public void fill() { System.out.println("fill() " + iterations + " times"); int count = 0; while (true) { try { // Allocations MyList next = new MyList(arraySize); list.add(next); MyRefList nextRef = new MyRefList(next, rq); refList.add(nextRef); } catch (OutOfMemoryError e) { // When the heap is full try { if (count++ > iterations) { return; } System.out.println("Freeing list"); while (!list.isEmpty()) { list.removeFirst(); } System.out.println("Doing work"); int j = 0; for (int i = 1; i < workUnits; i++) { j = j + i; } System.out.println("Clearing refs"); ListIterator listIt = refList.listIterator(); while (listIt.hasNext()) { MyRefList next = (MyRefList) listIt.next(); next.clearReferent(); } System.gc(); System.out.println("Freeing refs"); while (!refList.isEmpty()) { refList.removeFirst(); } } catch (OutOfMemoryError e2) { System.err.println("Out of Memory - 2 "); continue; } } catch (Exception e) { System.err.println("Unexpected exception: " + e); return; } } } /** * Test entry point. * args[0] - array size (is the size of the int array in a list item) * args[1] - iterations (is the number of out-of-memory exceptions before exit) * args[2] - work (is the work done between allocations) * @param args */ public static void main(String[] args) { // Get the input parameters. if (args.length != 3) { throw new IllegalArgumentException("Wrong number of input argumets"); } int as = Integer.parseInt(args[0]); int cnt = Integer.parseInt(args[1]); int work = Integer.parseInt(args[2]); System.out.println(" " + as + "\n" + " " + cnt + "\n" + " " + work + "\n"); // Initialization TestBubbleUpRef b = new TestBubbleUpRef(as, cnt, work); // Run the test try { b.fill(); } catch (OutOfMemoryError e) { b = null; // Free memory before trying to print anything System.err.println("Out of Memory - exiting "); } catch (Exception e) { System.err.println("Exiting "); } } }