Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/lang/ref/ReferenceEnqueuePending.java
38812 views
/*1* Copyright (c) 2011, 2013, 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/* @test24* @bug 424397825* @summary Test if Reference.enqueue() works properly with pending references26*/27import java.lang.ref.*;2829public class ReferenceEnqueuePending {30static class NumberedWeakReference extends WeakReference<Integer> {31// Add an integer to identify the weak reference object.32int number;3334NumberedWeakReference(Integer referent, ReferenceQueue<Integer> q, int i) {35super(referent, q);36number = i;37}38}3940final static boolean debug = System.getProperty("test.debug") != null;41final static int iterations = 1000;42final static int gc_trigger = 99;43static int[] a = new int[2 * iterations];44// Keep all weak references alive with the following array.45static NumberedWeakReference[] b = new NumberedWeakReference[iterations];4647public static void main(String[] argv) throws Exception {48if (debug) {49System.out.println("Starting the test.");50}51// Raise thread priority to match the referenceHandler52// priority, so that they can race also on a uniprocessor.53raisePriority();5455ReferenceQueue<Integer> refQueue = new ReferenceQueue<>();5657// Our objective is to let the mutator enqueue58// a Reference object that may already be in the59// pending state because of having been identified60// as weakly reachable at a previous garbage collection.61// To this end, we create many Reference objects, each with a62// a unique integer object as its referant.63// We let the referents become eligible for collection,64// while racing with the garbage collector which may65// have pended some of these Reference objects.66// Finally we check that all of the Reference objects67// end up on the their queue. The test was originally68// submitted to show that such races could break the69// pending list and/or the reference queue, because of sharing70// the same link ("next") for maintaining both lists, thus71// losing some of the Reference objects on either queue.7273Integer obj = new Integer(0);74NumberedWeakReference weaky = new NumberedWeakReference(obj, refQueue, 0);75for (int i = 1; i < iterations; i++) {76// Create a new object, dropping the onlY strong reference to77// the previous Integer object.78obj = new Integer(i);79// Trigger gc each gc_trigger iterations.80if ((i % gc_trigger) == 0) {81forceGc(0);82}83// Enqueue every other weaky.84if ((i % 2) == 0) {85weaky.enqueue();86}87// Remember the Reference objects, for testing later.88b[i - 1] = weaky;89// Get a new weaky for the Integer object just90// created, which may be explicitly enqueued in91// our next trip around the loop.92weaky = new NumberedWeakReference(obj, refQueue, i);93}9495// Do a final collection to discover and process all96// Reference objects created above, allowing enough time97// for the ReferenceHandler thread to queue the References.98forceGc(100);99forceGc(100);100101// Verify that all WeakReference objects ended up queued.102checkResult(refQueue, obj, iterations-1);103System.out.println("Test passed.");104}105106private static void checkResult(ReferenceQueue<Integer> queue,107Integer obj,108int expected) {109if (debug) {110System.out.println("Reading the queue");111}112113// Empty the queue and record numbers into a[];114NumberedWeakReference weakRead = (NumberedWeakReference) queue.poll();115int length = 0;116while (weakRead != null) {117a[length++] = weakRead.number;118weakRead = (NumberedWeakReference) queue.poll();119}120if (debug) {121System.out.println("Reference Queue had " + length + " elements");122}123// Use the last Reference object of those created above, so as to keep it "alive".124System.out.println("I must write " + obj + " to prevent compiler optimizations.");125126127// verify the queued references: all but the last Reference object128// should have been in the queue.129if (debug) {130System.out.println("Start of final check");131}132133// Sort the first "length" elements in array "a[]".134sort(length);135136boolean fail = (length != expected);137for (int i = 0; i < length; i++) {138if (a[i] != i) {139if (debug) {140System.out.println("a[" + i + "] is not " + i + " but " + a[i]);141}142fail = true;143}144}145if (fail) {146printMissingElements(length, expected);147throw new RuntimeException("TEST FAILED: only " + length148+ " reference objects have been queued out of "149+ expected);150}151}152153private static void printMissingElements(int length, int expected) {154System.out.println("The following numbers were not found in the reference queue: ");155int missing = 0;156int element = 0;157for (int i = 0; i < length; i++) {158while ((a[i] != element) & (element < expected)) {159System.out.print(element + " ");160if (missing % 20 == 19) {161System.out.println(" ");162}163missing++;164element++;165}166element++;167}168System.out.print("\n");169}170171private static void forceGc(long millis) throws InterruptedException {172Runtime.getRuntime().gc();173Thread.sleep(millis);174}175176// Bubble sort the first "length" elements in array "a".177private static void sort(int length) {178int hold;179if (debug) {180System.out.println("Sorting. Length=" + length);181}182for (int pass = 1; pass < length; pass++) { // passes over the array183for (int i = 0; i < length - pass; i++) { // a single pass184if (a[i] > a[i + 1]) { // then swap185hold = a[i];186a[i] = a[i + 1];187a[i + 1] = hold;188}189} // End of i loop190} // End of pass loop191}192193// Raise thread priority so as to increase the194// probability of the mutator succeeding in enqueueing195// an object that is still in the pending state.196// This is (probably) only required for a uniprocessor.197static void raisePriority() {198Thread tr = Thread.currentThread();199tr.setPriority(Thread.MAX_PRIORITY);200}201} // End of class ReferenceEnqueuePending202203204