1/*
2 * Copyright (c) 2004, 2016, 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
24import java.lang.ref.ReferenceQueue;
25import java.lang.ref.WeakReference;
26import java.util.LinkedList;
27import java.util.ListIterator;
28
29/*
30 * @test
31 * @requires vm.gc.ConcMarkSweep
32 * @key cte_test
33 * @bug 4950157
34 * @summary Stress the behavior of ergonomics when the heap is nearly full and
35 *          stays nearly full.
36 * @run main/othervm
37 *  -XX:+UseConcMarkSweepGC -XX:-CMSYield -XX:-CMSPrecleanRefLists1
38 *  -XX:CMSInitiatingOccupancyFraction=0 -Xmx80m TestBubbleUpRef 16000 50 10000
39 */
40
41/**
42 * Test program to stress the behavior of ergonomics when the
43 * heap is nearly full and stays nearly full.
44 * This is a test to catch references that have been discovered
45 * during concurrent marking and whose referents have been
46 * cleared by the mutator.
47 * Allocate objects with weak references until the heap is full
48 * Free the objects.
49 * Do work so that concurrent marking has a chance to work
50 * Clear the referents out of the weak references
51 * System.gc() in the hopes that it will acquire the collection
52 * Free the weak references
53 * Do it again.
54 *
55 * Use the following VM options
56 *     -Xmx80m -XX:-CMSYield [-XX:+UseConcMarkSweepGC] -XX:-CMSPrecleanRefLists1
57 *      -XX:CMSInitiatingOccupancyFraction=0
58 *
59 * Use parameter:
60 *     args[0] - array size  (16000)
61 *     args[1] - iterations  (50)
62 *     args[2] - work        (10000)
63 */
64class MyList extends LinkedList {
65
66    int[] a;
67
68    MyList(int size) {
69        a = new int[size];
70    }
71}
72
73class MyRefList extends LinkedList {
74
75    WeakReference ref;
76
77    MyRefList(Object o, ReferenceQueue rq) {
78        ref = new WeakReference(o, rq);
79    }
80
81    void clearReferent() {
82        ref.clear();
83    }
84}
85
86public class TestBubbleUpRef {
87
88    MyList list;
89    MyRefList refList;
90    ReferenceQueue rq;
91    int refListLen;
92    int arraySize;
93    int iterations;
94    int workUnits;
95
96    TestBubbleUpRef(int as, int cnt, int wk) {
97        arraySize = as;
98        iterations = cnt;
99        workUnits = wk;
100        list = new MyList(arraySize);
101        refList = new MyRefList(list, rq);
102    }
103
104    public void fill() {
105        System.out.println("fill() " + iterations + " times");
106        int count = 0;
107        while (true) {
108            try {
109                // Allocations
110                MyList next = new MyList(arraySize);
111                list.add(next);
112                MyRefList nextRef = new MyRefList(next, rq);
113                refList.add(nextRef);
114            } catch (OutOfMemoryError e) {
115                // When the heap is full
116                try {
117                    if (count++ > iterations) {
118                        return;
119                    }
120                    System.out.println("Freeing list");
121                    while (!list.isEmpty()) {
122                        list.removeFirst();
123                    }
124                    System.out.println("Doing work");
125                    int j = 0;
126                    for (int i = 1; i < workUnits; i++) {
127                        j = j + i;
128                    }
129                    System.out.println("Clearing refs");
130                    ListIterator listIt = refList.listIterator();
131                    while (listIt.hasNext()) {
132                        MyRefList next = (MyRefList) listIt.next();
133                        next.clearReferent();
134                    }
135                    System.gc();
136                    System.out.println("Freeing refs");
137                    while (!refList.isEmpty()) {
138                        refList.removeFirst();
139                    }
140                } catch (OutOfMemoryError e2) {
141                    System.err.println("Out of Memory - 2 ");
142                    continue;
143                }
144            } catch (Exception e) {
145                System.err.println("Unexpected exception: " + e);
146                return;
147            }
148        }
149    }
150
151    /**
152     * Test entry point.
153     *     args[0] - array size  (is the size of the int array in a list item)
154     *     args[1] - iterations  (is the number of out-of-memory exceptions before exit)
155     *     args[2] - work        (is the work done between allocations)
156     * @param args
157     */
158    public static void main(String[] args) {
159        // Get the input parameters.
160        if (args.length != 3) {
161            throw new IllegalArgumentException("Wrong number of input argumets");
162        }
163
164        int as = Integer.parseInt(args[0]);
165        int cnt = Integer.parseInt(args[1]);
166        int work = Integer.parseInt(args[2]);
167
168        System.out.println("<array size> " + as + "\n"
169                + "<OOM's> " + cnt + "\n"
170                + "<work units> " + work + "\n");
171
172        // Initialization
173        TestBubbleUpRef b = new TestBubbleUpRef(as, cnt, work);
174
175        // Run the test
176        try {
177            b.fill();
178        } catch (OutOfMemoryError e) {
179            b = null; // Free memory before trying to print anything
180            System.err.println("Out of Memory - exiting ");
181        } catch (Exception e) {
182            System.err.println("Exiting ");
183        }
184    }
185}
186
187