Skip to content
This repository was archived by the owner on Oct 1, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion jdk/src/share/classes/java/lang/ref/FinalReference.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
Expand Down Expand Up @@ -33,4 +33,9 @@ class FinalReference<T> extends Reference<T> {
public FinalReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}

@Override
public boolean enqueue() {
throw new InternalError("should never reach here");
}
}
8 changes: 3 additions & 5 deletions jdk/src/share/classes/java/lang/ref/Reference.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@ public void clear() {
this.referent = null;
}


/* -- Queue operations -- */

/**
Expand All @@ -230,8 +229,8 @@ public boolean isEnqueued() {
}

/**
* Adds this reference object to the queue with which it is registered,
* if any.
* Clears this reference object and adds it to the queue with which
* it is registered, if any.
*
* <p> This method is invoked only by Java code; when the garbage collector
* enqueues references it does so directly, without invoking this method.
Expand All @@ -241,10 +240,10 @@ public boolean isEnqueued() {
* it was not registered with a queue when it was created
*/
public boolean enqueue() {
this.referent = null;
return this.queue.enqueue(this);
}


/* -- Constructors -- */

Reference(T referent) {
Expand All @@ -255,5 +254,4 @@ public boolean enqueue() {
this.referent = referent;
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}

}
52 changes: 49 additions & 3 deletions jdk/test/java/lang/ref/ReferenceEnqueue.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2017, 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
Expand All @@ -22,17 +22,22 @@
*/

/* @test
* @bug 4268317
* @bug 4268317 8175797
* @summary Test if Reference.enqueue() works properly with GC
* @run main ReferenceEnqueue
*/

import java.lang.ref.*;
import java.util.ArrayList;
import java.util.List;

public class ReferenceEnqueue {

public static void main(String args[]) throws Exception {
for (int i=0; i < 5; i++)
for (int i=0; i < 5; i++) {
new WeakRef().run();
new ExplicitEnqueue().run();
}
System.out.println("Test passed.");
}

Expand Down Expand Up @@ -76,4 +81,45 @@ void run() throws InterruptedException {
}
}
}

static class ExplicitEnqueue {
final ReferenceQueue<Object> queue = new ReferenceQueue<>();
final List<Reference<Object>> refs = new ArrayList<>();
final int iterations = 1000;

ExplicitEnqueue() {
this.refs.add(new SoftReference<>(new Object(), queue));
this.refs.add(new WeakReference<>(new Object(), queue));
// Can't test PhantomReference because get() always returns null.
}

void run() throws InterruptedException {
for (Reference<Object> ref : refs) {
if (ref.enqueue() == false) {
throw new RuntimeException("Error: enqueue failed");
}
if (ref.get() != null) {
throw new RuntimeException("Error: referent must be cleared");
}
}

System.gc();
for (int i = 0; refs.size() > 0 && i < iterations; i++) {
Reference<Object> ref = (Reference<Object>)queue.poll();
if (ref == null) {
System.gc();
Thread.sleep(100);
continue;
}

if (refs.remove(ref) == false) {
throw new RuntimeException("Error: unknown reference " + ref);
}
}

if (!refs.isEmpty()) {
throw new RuntimeException("Error: not all references are removed");
}
}
}
}