On Wed, 9 Apr 2025 11:43:16 GMT, Chen Liang <li...@openjdk.org> wrote:
>> In LinkedBlockingDeque.addAll() we first build up the chain of nodes and >> then add that chain in bulk to the existing nodes. We count the nodes in >> "int n" and then whilst holding the lock, we check that we haven't exceeded >> the capacity with "if (count + n <= capacity)". However, if we pass in a >> collection that has more than Integer.MAX_VALUE items in it, then we can >> overflow n, making it negative. Since "count + n" is also negative, we can >> add the chain to our last item, and thus we end up with a >> LinkedBlockingDeque with more than Integer.MAX_VALUE of items and a negative >> size(). stream().count() gives the correct number of items. >> >> This happens both via the bulk add constructor >> LinkedBlockingDeque(Collection) and when we call addAll(Collection) directly. >> >> In Java 8, they didn't have the clever addAll() method, and thus it failed >> immediately. >> >> Here is some test code: >> >> >> import java.util.*; >> import java.util.concurrent.*; >> >> // To see the issue, run with at least 90 GB of memory: >> // -XX:+UnlockExperimentalVMOptions -Xmx90g -Xms90g -XX:+UseEpsilonGC >> -verbose:gc >> // To verify the fix, run with at least 200 GB of memory: >> // -XX:+UnlockExperimentalVMOptions -Xmx200g -Xms200g -XX:+UseEpsilonGC >> -verbose:gc >> // To try on older versions of Java that don't have the EpsilonGC, you can >> use: >> // -XX:+UseG1GC -verbose:gc -Xmx91g -Xms91g -XX:NewSize=89g >> public class NegativeSizedLinkedBlockingDeque { >> public static void main(String... args) { >> HUUUGECollection list = new HUUUGECollection(Integer.MAX_VALUE + 1L); >> LinkedBlockingDeque<Integer> lbd = new LinkedBlockingDeque<>(10); >> lbd.addAll(list); >> System.out.println("lbd.size() = " + lbd.size()); >> System.out.println(lbd.stream().count()); >> } >> >> public static class HUUUGECollection extends AbstractCollection<Integer> >> { >> private final long size; >> >> public HUUUGECollection(long size) { >> this.size = size; >> } >> >> @Override >> public int size() { >> return size < Integer.MAX_VALUE ? (int) size : Integer.MAX_VALUE; >> } >> >> @Override >> public Iterator<Integer> iterator() { >> return new Iterator<Integer>() { >> private long count = 0; >> >> public boolean hasNext() { >> return count < size; >> } >> >> public Integer next() { >> if (!hasNext()... > > Hi @kabutz, I believe you can create issues on JBS (bugs.openjdk.org) > directly without going thorough bugs.java.com - as an author in OpenJDK > census, you have an account associated with your email, and you can log in to > the JBS at > https://id.openjdk.org/console/login?backUrl=https://bugs.openjdk.org and > from there, you can create or edit issues or CSRs. Thanks @liach, I'm just not sure about all the fields in the OpenJDK census - will try do that next time. ------------- PR Comment: https://git.openjdk.org/jdk/pull/24538#issuecomment-2789503132