diff --git a/jdk/src/share/classes/java/lang/ref/FinalReference.java b/jdk/src/share/classes/java/lang/ref/FinalReference.java index d763794372..bb97d6947a 100644 --- a/jdk/src/share/classes/java/lang/ref/FinalReference.java +++ b/jdk/src/share/classes/java/lang/ref/FinalReference.java @@ -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 @@ -33,4 +33,9 @@ class FinalReference extends Reference { public FinalReference(T referent, ReferenceQueue q) { super(referent, q); } + + @Override + public boolean enqueue() { + throw new InternalError("should never reach here"); + } } diff --git a/jdk/src/share/classes/java/lang/ref/Reference.java b/jdk/src/share/classes/java/lang/ref/Reference.java index 42d2ba9781..f1c958bffd 100644 --- a/jdk/src/share/classes/java/lang/ref/Reference.java +++ b/jdk/src/share/classes/java/lang/ref/Reference.java @@ -213,7 +213,6 @@ public void clear() { this.referent = null; } - /* -- Queue operations -- */ /** @@ -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. * *

This method is invoked only by Java code; when the garbage collector * enqueues references it does so directly, without invoking this method. @@ -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) { @@ -255,5 +254,4 @@ public boolean enqueue() { this.referent = referent; this.queue = (queue == null) ? ReferenceQueue.NULL : queue; } - } diff --git a/jdk/test/java/lang/ref/ReferenceEnqueue.java b/jdk/test/java/lang/ref/ReferenceEnqueue.java index 25907a034c..33f8e27e45 100644 --- a/jdk/test/java/lang/ref/ReferenceEnqueue.java +++ b/jdk/test/java/lang/ref/ReferenceEnqueue.java @@ -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 @@ -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."); } @@ -76,4 +81,45 @@ void run() throws InterruptedException { } } } + + static class ExplicitEnqueue { + final ReferenceQueue queue = new ReferenceQueue<>(); + final List> 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 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 ref = (Reference)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"); + } + } + } }