< prev index next > test/jdk/java/lang/ref/ReferenceEnqueuePending.java
Print this page
/*
! * Copyright (c) 2011, 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.
/*
! * Copyright (c) 2011, 2024, 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.
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test
! * @bug 4243978
* @summary Test if Reference.enqueue() works properly with pending references
*/
import java.lang.ref.*;
public class ReferenceEnqueuePending {
! static class NumberedWeakReference extends WeakReference<Integer> {
// Add an integer to identify the weak reference object.
int number;
! NumberedWeakReference(Integer referent, ReferenceQueue<Integer> q, int i) {
super(referent, q);
number = i;
}
}
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test
! * @bug 4243978 8336671
* @summary Test if Reference.enqueue() works properly with pending references
*/
import java.lang.ref.*;
+ import java.util.Arrays;
public class ReferenceEnqueuePending {
!
+ record Numbered(int number) {}
+
+ static class NumberedWeakReference extends WeakReference<Numbered> {
// Add an integer to identify the weak reference object.
int number;
! NumberedWeakReference(Numbered referent, ReferenceQueue<Numbered> q, int i) {
super(referent, q);
number = i;
}
}
}
// Raise thread priority to match the referenceHandler
// priority, so that they can race also on a uniprocessor.
raisePriority();
! ReferenceQueue<Integer> refQueue = new ReferenceQueue<>();
// Our objective is to let the mutator enqueue
// a Reference object that may already be in the
// pending state because of having been identified
// as weakly reachable at a previous garbage collection.
! // To this end, we create many Reference objects, each with a
! // a unique integer object as its referant.
// We let the referents become eligible for collection,
// while racing with the garbage collector which may
// have pended some of these Reference objects.
! // Finally we check that all of the Reference objects
! // end up on the their queue. The test was originally
// submitted to show that such races could break the
// pending list and/or the reference queue, because of sharing
// the same link ("next") for maintaining both lists, thus
// losing some of the Reference objects on either queue.
! Integer obj = new Integer(0);
NumberedWeakReference weaky = new NumberedWeakReference(obj, refQueue, 0);
for (int i = 1; i < iterations; i++) {
! // Create a new object, dropping the onlY strong reference to
! // the previous Integer object.
! obj = new Integer(i);
// Trigger gc each gc_trigger iterations.
if ((i % gc_trigger) == 0) {
forceGc(0);
}
// Enqueue every other weaky.
if ((i % 2) == 0) {
weaky.enqueue();
}
// Remember the Reference objects, for testing later.
b[i - 1] = weaky;
! // Get a new weaky for the Integer object just
// created, which may be explicitly enqueued in
// our next trip around the loop.
weaky = new NumberedWeakReference(obj, refQueue, i);
}
}
// Raise thread priority to match the referenceHandler
// priority, so that they can race also on a uniprocessor.
raisePriority();
! ReferenceQueue<Numbered> refQueue = new ReferenceQueue<>();
// Our objective is to let the mutator enqueue
// a Reference object that may already be in the
// pending state because of having been identified
// as weakly reachable at a previous garbage collection.
! // To this end, we create many Reference objects, each with
! // a unique Numbered object as its referant.
// We let the referents become eligible for collection,
// while racing with the garbage collector which may
// have pended some of these Reference objects.
! // Finally, we check that all of the Reference objects
! // end up on their queue. The test was originally
// submitted to show that such races could break the
// pending list and/or the reference queue, because of sharing
// the same link ("next") for maintaining both lists, thus
// losing some of the Reference objects on either queue.
! Numbered obj = new Numbered(0);
NumberedWeakReference weaky = new NumberedWeakReference(obj, refQueue, 0);
for (int i = 1; i < iterations; i++) {
! // Create a new object, dropping the only strong reference to
! // the previous Numbered object.
! obj = new Numbered(i);
// Trigger gc each gc_trigger iterations.
if ((i % gc_trigger) == 0) {
forceGc(0);
}
// Enqueue every other weaky.
if ((i % 2) == 0) {
weaky.enqueue();
}
// Remember the Reference objects, for testing later.
b[i - 1] = weaky;
! // Get a new weaky for the Numbered object just
// created, which may be explicitly enqueued in
// our next trip around the loop.
weaky = new NumberedWeakReference(obj, refQueue, i);
}
Reference.reachabilityFence(obj);
System.out.println("Test passed.");
}
! private static NumberedWeakReference waitForReference(ReferenceQueue<Integer> queue) {
try {
return (NumberedWeakReference) queue.remove(30000); // 30sec
} catch (InterruptedException ie) {
return null;
}
}
! private static void checkResult(ReferenceQueue<Integer> queue,
int expected) {
if (debug) {
System.out.println("Reading the queue");
}
Reference.reachabilityFence(obj);
System.out.println("Test passed.");
}
! private static NumberedWeakReference waitForReference(ReferenceQueue<Numbered> queue) {
try {
return (NumberedWeakReference) queue.remove(30000); // 30sec
} catch (InterruptedException ie) {
return null;
}
}
! private static void checkResult(ReferenceQueue<Numbered> queue,
int expected) {
if (debug) {
System.out.println("Reading the queue");
}
if (debug) {
System.out.println("Start of final check");
}
// Sort the first "length" elements in array "a[]".
! sort(length);
boolean fail = (length != expected);
for (int i = 0; i < length; i++) {
if (a[i] != i) {
if (debug) {
if (debug) {
System.out.println("Start of final check");
}
// Sort the first "length" elements in array "a[]".
! Arrays.sort(a, 0, length);
boolean fail = (length != expected);
for (int i = 0; i < length; i++) {
if (a[i] != i) {
if (debug) {
private static void forceGc(long millis) throws InterruptedException {
Runtime.getRuntime().gc();
Thread.sleep(millis);
}
- // Bubble sort the first "length" elements in array "a".
- private static void sort(int length) {
- int hold;
- if (debug) {
- System.out.println("Sorting. Length=" + length);
- }
- for (int pass = 1; pass < length; pass++) { // passes over the array
- for (int i = 0; i < length - pass; i++) { // a single pass
- if (a[i] > a[i + 1]) { // then swap
- hold = a[i];
- a[i] = a[i + 1];
- a[i + 1] = hold;
- }
- } // End of i loop
- } // End of pass loop
- }
-
// Raise thread priority so as to increase the
// probability of the mutator succeeding in enqueueing
// an object that is still in the pending state.
// This is (probably) only required for a uniprocessor.
static void raisePriority() {
< prev index next >