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

Reply via email to