# HG changeset patch # User dl # Date 1456620897 28800 # Node ID 98d40e72833efeb72b62a784eac06bb57727e656 # Parent 6e5619283b00dfc6880d07683575744e9496dc46 8054446: Repeated offer and remove on ConcurrentLinkedQueue lead to an OutOfMemoryError Reviewed-by: martin, rasbold diff -r 6e5619283b00 -r 98d40e72833e src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java --- a/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Mon Jul 20 18:02:41 2020 +0100 +++ b/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Sat Feb 27 16:54:57 2016 -0800 @@ -484,19 +484,25 @@ * @return {@code true} if this queue changed as a result of the call */ public boolean remove(Object o) { - if (o == null) return false; - Node pred = null; - for (Node p = first(); p != null; p = succ(p)) { - E item = p.item; - if (item != null && - o.equals(item) && - p.casItem(item, null)) { - Node next = succ(p); - if (pred != null && next != null) + if (o != null) { + Node next, pred = null; + for (Node p = first(); p != null; pred = p, p = next) { + boolean removed = false; + E item = p.item; + if (item != null) { + if (!o.equals(item)) { + next = succ(p); + continue; + } + removed = p.casItem(item, null); + } + + next = succ(p); + if (pred != null && next != null) // unlink pred.casNext(p, next); - return true; + if (removed) + return true; } - pred = p; } return false; } diff -r 6e5619283b00 -r 98d40e72833e test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java Sat Feb 27 16:54:57 2016 -0800 @@ -0,0 +1,60 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Martin Buchholz with assistance from members of JCP + * JSR-166 Expert Group and released to the public domain, as + * explained at http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/* + * @test + * @bug 8054446 8137184 8137185 + * @summary Regression test for memory leak in remove(Object) + * @run main/othervm -Xmx2200k RemoveLeak + */ + +import java.util.concurrent.ConcurrentLinkedQueue; + +public class RemoveLeak { + public static void main(String[] args) { + int i = 0; + // Without bug fix, OutOfMemoryError was observed at iteration 65120 + int iterations = 10 * 65120; + try { + ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); + queue.add(0L); + while (i++ < iterations) { + queue.add(1L); + queue.remove(1L); + } + } catch (Error t) { + System.err.printf("failed at iteration %d/%d%n", i, iterations); + throw t; + } + } +}