Sometimes constraints are questionable

James Laskey james.laskey at oracle.com
Sat May 30 16:51:04 UTC 2020


Understood. Just trying to balance correctness with providing meaningful exceptions. 

I suppose another approach is to let it all go deep and catch the error on the way back and provide the detail then. Not likely win any fans. 

��

> On May 30, 2020, at 12:30 PM, Martin Buchholz <martinrb at google.com> wrote:
> 
> I wrote an earlier version of this grow logic, and then it was
> transplanted into other classes.
> 
> We strongly suspect that the VM will throw OOME when we try to
> allocate an array beyond MAX_ARRAY_SIZE, so are reluctant to do so,
> but we also consider the VM behavior a bug that may eventually get
> fixed (or is already a non-issue with a different VM).  We are trying
> for good behavior with both sorts of VM.
> 
>> On Sat, May 30, 2020 at 7:32 AM Jim Laskey <james.laskey at oracle.com> wrote:
>> 
>> I'm working through https://bugs.openjdk.java.net/browse/JDK-8230744 <https://bugs.openjdk.java.net/browse/JDK-8230744> Several classes throw OutOfMemoryError without message .
>> 
>> I'm wondering why hugeCapacity in src/jdk.zipfs/share/classes/jdk/nio/zipfs/ByteArrayChannel.java is defined as
>> 
>>    /**
>>     * The maximum size of array to allocate.
>>     * Some VMs reserve some header words in an array.
>>     * Attempts to allocate larger arrays may result in
>>     * OutOfMemoryError: Requested array size exceeds VM limit
>>     */
>>    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
>> 
>>    /**
>>     * Increases the capacity to ensure that it can hold at least the
>>     * number of elements specified by the minimum capacity argument.
>>     *
>>     * @param minCapacity the desired minimum capacity
>>     */
>>    private void grow(int minCapacity) {
>>        // overflow-conscious code
>>        int oldCapacity = buf.length;
>>        int newCapacity = oldCapacity << 1;
>>        if (newCapacity - minCapacity < 0)
>>            newCapacity = minCapacity;
>>        if (newCapacity - MAX_ARRAY_SIZE > 0)
>>            newCapacity = hugeCapacity(minCapacity);
>>        buf = Arrays.copyOf(buf, newCapacity);
>>    }
>> 
>>    private static int hugeCapacity(int minCapacity) {
>>        if (minCapacity < 0) // overflow
>>            throw new OutOfMemoryError();
>>        return (minCapacity > MAX_ARRAY_SIZE) ?
>>            Integer.MAX_VALUE :
>>            MAX_ARRAY_SIZE;
>>    }
>> 
>> It just seems that it's pushing the inevitable off to Arrays.copyOf.  Shouldn't it be:
>> 
>>    private static int hugeCapacity(int minCapacity) {
>>        if (minCapacity < 0 || minCapacity > MAX_ARRAY_SIZE) {
>>            throw
>>                new OutOfMemoryError("ByteArrayChannel exceeds maximum size: " +
>>                                      MAX_ARRAY_SIZE);
>>        }
>> 
>>        return MAX_ARRAY_SIZE;
>>    }
>> 
>> Real question: is there some hidden purpose behind this kind of logic?
>> 
>> 
>> Cheers,
>> 
>> -- Jim
>> 
>> 



More information about the core-libs-dev mailing list