< prev index next >

test/jdk/java/lang/ref/ReferenceEnqueuePending.java

Print this page

  1 /*
  2  * Copyright (c) 2011, 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 
 24 /* @test
 25  * @bug 4243978
 26  * @summary Test if Reference.enqueue() works properly with pending references
 27  */
 28 import java.lang.ref.*;

 29 
 30 public class ReferenceEnqueuePending {
 31     static class NumberedWeakReference extends WeakReference<Integer> {



 32         //  Add an integer to identify the weak reference object.
 33         int number;
 34 
 35         NumberedWeakReference(Integer referent, ReferenceQueue<Integer> q, int i) {
 36             super(referent, q);
 37             number = i;
 38         }
 39     }
 40 
 41     static final boolean debug = System.getProperty("test.debug") != null;
 42     static final int iterations = 1000;
 43     static final int gc_trigger = 99;
 44     static int[] a = new int[2 * iterations];
 45     // Keep all weak references alive with the following array.
 46     static NumberedWeakReference[] b = new NumberedWeakReference[iterations];
 47 
 48     public static void main(String[] argv) throws Exception {
 49         if (debug) {
 50             System.out.println("Starting the test.");
 51         }
 52         // Raise thread priority to match the referenceHandler
 53         // priority, so that they can race also on a uniprocessor.
 54         raisePriority();
 55 
 56         ReferenceQueue<Integer> refQueue = new ReferenceQueue<>();
 57 
 58         // Our objective is to let the mutator enqueue
 59         // a Reference object that may already be in the
 60         // pending state because of having been identified
 61         // as weakly reachable at a previous garbage collection.
 62         // To this end, we create many Reference objects, each with a
 63         // a unique integer object as its referant.
 64         // We let the referents become eligible for collection,
 65         // while racing with the garbage collector which may
 66         // have pended some of these Reference objects.
 67         // Finally we check that all of the Reference objects
 68         // end up on the their queue. The test was originally
 69         // submitted to show that such races could break the
 70         // pending list and/or the reference queue, because of sharing
 71         // the same link ("next") for maintaining both lists, thus
 72         // losing some of the Reference objects on either queue.
 73 
 74         Integer obj = new Integer(0);
 75         NumberedWeakReference weaky = new NumberedWeakReference(obj, refQueue, 0);
 76         for (int i = 1; i < iterations; i++) {
 77             // Create a new object, dropping the onlY strong reference to
 78             // the previous Integer object.
 79             obj = new Integer(i);
 80             // Trigger gc each gc_trigger iterations.
 81             if ((i % gc_trigger) == 0) {
 82                 forceGc(0);
 83             }
 84             // Enqueue every other weaky.
 85             if ((i % 2) == 0) {
 86                 weaky.enqueue();
 87             }
 88             // Remember the Reference objects, for testing later.
 89             b[i - 1] = weaky;
 90             // Get a new weaky for the Integer object just
 91             // created, which may be explicitly enqueued in
 92             // our next trip around the loop.
 93             weaky = new NumberedWeakReference(obj, refQueue, i);
 94         }
 95 
 96         // Do a final collection to discover and process all
 97         // Reference objects created above, allowing some time
 98         // for the ReferenceHandler thread to queue the References.
 99         forceGc(100);
100         forceGc(100);
101 
102         // Verify that all WeakReference objects ended up queued.
103         checkResult(refQueue, iterations-1);
104 
105         // Ensure the final weaky is live but won't be enqueued during
106         // result checking, by ensuring its referent remains live.
107         // This eliminates behavior changes resulting from different
108         // compiler optimizations.
109         Reference.reachabilityFence(weaky);
110         Reference.reachabilityFence(obj);
111 
112         System.out.println("Test passed.");
113     }
114 
115     private static NumberedWeakReference waitForReference(ReferenceQueue<Integer> queue) {
116         try {
117             return (NumberedWeakReference) queue.remove(30000); // 30sec
118         } catch (InterruptedException ie) {
119             return null;
120         }
121     }
122 
123     private static void checkResult(ReferenceQueue<Integer> queue,
124                                     int expected) {
125         if (debug) {
126             System.out.println("Reading the queue");
127         }
128 
129         // Empty the queue and record numbers into a[];
130         NumberedWeakReference weakRead = waitForReference(queue);
131         int length = 0;
132         while (weakRead != null) {
133             a[length++] = weakRead.number;
134             if (length < expected) {
135                 weakRead = waitForReference(queue);
136             } else {            // Check for unexpected extra entries.
137                 weakRead = (NumberedWeakReference) queue.poll();
138             }
139         }
140         if (debug) {
141             System.out.println("Reference Queue had " + length + " elements");
142         }
143 
144 
145         // verify the queued references: all but the last Reference object
146         // should have been in the queue.
147         if (debug) {
148             System.out.println("Start of final check");
149         }
150 
151         // Sort the first "length" elements in array "a[]".
152         sort(length);
153 
154         boolean fail = (length != expected);
155         for (int i = 0; i < length; i++) {
156             if (a[i] != i) {
157                 if (debug) {
158                     System.out.println("a[" + i + "] is not " + i + " but " + a[i]);
159                 }
160                 fail = true;
161             }
162         }
163         if (fail) {
164              printMissingElements(length, expected);
165              throw new RuntimeException("TEST FAILED: only " + length
166                     + " reference objects have been queued out of "
167                     + expected);
168         }
169     }
170 
171     private static void printMissingElements(int length, int expected) {
172         System.out.println("The following numbers were not found in the reference queue: ");

174         int element = 0;
175         for (int i = 0; i < length; i++) {
176             while ((a[i] != element) & (element < expected)) {
177                 System.out.print(element + " ");
178                 if (missing % 20 == 19) {
179                     System.out.println(" ");
180                 }
181                 missing++;
182                 element++;
183             }
184             element++;
185         }
186         System.out.print("\n");
187     }
188 
189     private static void forceGc(long millis) throws InterruptedException {
190         Runtime.getRuntime().gc();
191         Thread.sleep(millis);
192     }
193 
194     // Bubble sort the first "length" elements in array "a".
195     private static void sort(int length) {
196         int hold;
197         if (debug) {
198             System.out.println("Sorting. Length=" + length);
199         }
200         for (int pass = 1; pass < length; pass++) {    // passes over the array
201             for (int i = 0; i < length - pass; i++) {  //  a single pass
202                 if (a[i] > a[i + 1]) {  // then swap
203                     hold = a[i];
204                     a[i] = a[i + 1];
205                     a[i + 1] = hold;
206                 }
207             }  // End of i loop
208         } // End of pass loop
209     }
210 
211     // Raise thread priority so as to increase the
212     // probability of the mutator succeeding in enqueueing
213     // an object that is still in the pending state.
214     // This is (probably) only required for a uniprocessor.
215     static void raisePriority() {
216         Thread tr = Thread.currentThread();
217         tr.setPriority(Thread.MAX_PRIORITY);
218     }
219 }   // End of class ReferenceEnqueuePending

  1 /*
  2  * Copyright (c) 2011, 2024, 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 /* @test
 25  * @bug 4243978 8336671
 26  * @summary Test if Reference.enqueue() works properly with pending references
 27  */
 28 import java.lang.ref.*;
 29 import java.util.Arrays;
 30 
 31 public class ReferenceEnqueuePending {
 32 
 33     record Numbered(int number) {}
 34 
 35     static class NumberedWeakReference extends WeakReference<Numbered> {
 36         //  Add an integer to identify the weak reference object.
 37         int number;
 38 
 39         NumberedWeakReference(Numbered referent, ReferenceQueue<Numbered> q, int i) {
 40             super(referent, q);
 41             number = i;
 42         }
 43     }
 44 
 45     static final boolean debug = System.getProperty("test.debug") != null;
 46     static final int iterations = 1000;
 47     static final int gc_trigger = 99;
 48     static int[] a = new int[2 * iterations];
 49     // Keep all weak references alive with the following array.
 50     static NumberedWeakReference[] b = new NumberedWeakReference[iterations];
 51 
 52     public static void main(String[] argv) throws Exception {
 53         if (debug) {
 54             System.out.println("Starting the test.");
 55         }
 56         // Raise thread priority to match the referenceHandler
 57         // priority, so that they can race also on a uniprocessor.
 58         raisePriority();
 59 
 60         ReferenceQueue<Numbered> refQueue = new ReferenceQueue<>();
 61 
 62         // Our objective is to let the mutator enqueue
 63         // a Reference object that may already be in the
 64         // pending state because of having been identified
 65         // as weakly reachable at a previous garbage collection.
 66         // To this end, we create many Reference objects, each with
 67         // a unique Numbered object as its referant.
 68         // We let the referents become eligible for collection,
 69         // while racing with the garbage collector which may
 70         // have pended some of these Reference objects.
 71         // Finally, we check that all of the Reference objects
 72         // end up on their queue. The test was originally
 73         // submitted to show that such races could break the
 74         // pending list and/or the reference queue, because of sharing
 75         // the same link ("next") for maintaining both lists, thus
 76         // losing some of the Reference objects on either queue.
 77 
 78         Numbered obj = new Numbered(0);
 79         NumberedWeakReference weaky = new NumberedWeakReference(obj, refQueue, 0);
 80         for (int i = 1; i < iterations; i++) {
 81             // Create a new object, dropping the only strong reference to
 82             // the previous Numbered object.
 83             obj = new Numbered(i);
 84             // Trigger gc each gc_trigger iterations.
 85             if ((i % gc_trigger) == 0) {
 86                 forceGc(0);
 87             }
 88             // Enqueue every other weaky.
 89             if ((i % 2) == 0) {
 90                 weaky.enqueue();
 91             }
 92             // Remember the Reference objects, for testing later.
 93             b[i - 1] = weaky;
 94             // Get a new weaky for the Numbered object just
 95             // created, which may be explicitly enqueued in
 96             // our next trip around the loop.
 97             weaky = new NumberedWeakReference(obj, refQueue, i);
 98         }
 99 
100         // Do a final collection to discover and process all
101         // Reference objects created above, allowing some time
102         // for the ReferenceHandler thread to queue the References.
103         forceGc(100);
104         forceGc(100);
105 
106         // Verify that all WeakReference objects ended up queued.
107         checkResult(refQueue, iterations-1);
108 
109         // Ensure the final weaky is live but won't be enqueued during
110         // result checking, by ensuring its referent remains live.
111         // This eliminates behavior changes resulting from different
112         // compiler optimizations.
113         Reference.reachabilityFence(weaky);
114         Reference.reachabilityFence(obj);
115 
116         System.out.println("Test passed.");
117     }
118 
119     private static NumberedWeakReference waitForReference(ReferenceQueue<Numbered> queue) {
120         try {
121             return (NumberedWeakReference) queue.remove(30000); // 30sec
122         } catch (InterruptedException ie) {
123             return null;
124         }
125     }
126 
127     private static void checkResult(ReferenceQueue<Numbered> queue,
128                                     int expected) {
129         if (debug) {
130             System.out.println("Reading the queue");
131         }
132 
133         // Empty the queue and record numbers into a[];
134         NumberedWeakReference weakRead = waitForReference(queue);
135         int length = 0;
136         while (weakRead != null) {
137             a[length++] = weakRead.number;
138             if (length < expected) {
139                 weakRead = waitForReference(queue);
140             } else {            // Check for unexpected extra entries.
141                 weakRead = (NumberedWeakReference) queue.poll();
142             }
143         }
144         if (debug) {
145             System.out.println("Reference Queue had " + length + " elements");
146         }
147 
148 
149         // verify the queued references: all but the last Reference object
150         // should have been in the queue.
151         if (debug) {
152             System.out.println("Start of final check");
153         }
154 
155         // Sort the first "length" elements in array "a[]".
156         Arrays.sort(a, 0, length);
157 
158         boolean fail = (length != expected);
159         for (int i = 0; i < length; i++) {
160             if (a[i] != i) {
161                 if (debug) {
162                     System.out.println("a[" + i + "] is not " + i + " but " + a[i]);
163                 }
164                 fail = true;
165             }
166         }
167         if (fail) {
168              printMissingElements(length, expected);
169              throw new RuntimeException("TEST FAILED: only " + length
170                     + " reference objects have been queued out of "
171                     + expected);
172         }
173     }
174 
175     private static void printMissingElements(int length, int expected) {
176         System.out.println("The following numbers were not found in the reference queue: ");

178         int element = 0;
179         for (int i = 0; i < length; i++) {
180             while ((a[i] != element) & (element < expected)) {
181                 System.out.print(element + " ");
182                 if (missing % 20 == 19) {
183                     System.out.println(" ");
184                 }
185                 missing++;
186                 element++;
187             }
188             element++;
189         }
190         System.out.print("\n");
191     }
192 
193     private static void forceGc(long millis) throws InterruptedException {
194         Runtime.getRuntime().gc();
195         Thread.sleep(millis);
196     }
197 

















198     // Raise thread priority so as to increase the
199     // probability of the mutator succeeding in enqueueing
200     // an object that is still in the pending state.
201     // This is (probably) only required for a uniprocessor.
202     static void raisePriority() {
203         Thread tr = Thread.currentThread();
204         tr.setPriority(Thread.MAX_PRIORITY);
205     }
206 }   // End of class ReferenceEnqueuePending
< prev index next >