RFR: 8237521: Memory Access API fixes for 32-bit

David Holmes david.holmes at oracle.com
Fri Jan 24 06:35:42 UTC 2020


Hi Nick,

On 24/01/2020 3:32 pm, Nick Gasson wrote:
> Hi David,
> 
> On 01/24/20 12:17 pm, David Holmes wrote:
>>>
>>> That said, memory segments are not the only clients of
>>> Unsafe::allocateMemory - so if we decided that overflow is an issue
>>> that should be handled in clients, fine, but at least it should be
>>> evident somewhere in the javadoc of Unsafe::allocateMemory?
>>
>> I'm glad you raised that as it prompted me to examine Unsafe in more
>> detail. :)
>>
>> The onus is put on the caller to ensure arguments are valid. Unsafe
>> class docs state, and a number of methods like allocateMemory repeat:
>>
>>       * <em>Note:</em> It is the resposibility of the caller to make
>>       * sure arguments are checked before the methods are called. While
>>       * some rudimentary checks are performed on the input, the checks
>>       * are best effort and when performance is an overriding priority,
>>       * as when methods of this class are optimized by the runtime
>>       * compiler, some or all checks (if any) may be elided. Hence, the
>>       * caller must not rely on the checks and corresponding
>>       * exceptions!
>>
>> So although allocateMemory explicitly checks for size_t related overflow:
>>
>>       * @throws RuntimeException if the size is negative or too large
>>       *         for the native size_t type
>>
>> the caller should not be relying on that.
>>
>> The existing overflow check is done by checkSize(long size) which has:
>>
>>   if (ADDRESS_SIZE == 4) {
>>      // Note: this will also check for negative sizes
>>      if (!is32BitClean(size)) {
>>          throw invalidInput();
>>      }
>>   }
>>
>> where is32BitClean is defined as:
>>
>> value >>> 32 == 0;
>>
>> and so is incomplete as this doesn't take into account the possible
>> align up of "size" that the JVM allocation routine actually
>> performs. But even if we fix this, the caller is not supposed to rely on
>> it.
>>
>> In terms of fixing it ... it isn't clear to me whether this case should
>> be detected in the VM as Nick's patch does, or whether it should be
>> caught before hand in the checkSize Java code (though we don't really
>> know what the alignment requirement may be in the Java code). A
>> difference is that if we catch it in checkSize then we will throw
>> IllegalArgumentException, whereas Nick's approach results in
>> OutOfMemoryError. I think the IllegalArgumentException is actually
>> preferable here.
>>
> 
> How about we align the size up to ADDRESS_SIZE (== HeapWordSize) in
> Unsafe.allocateMemory() before the call to allocateMemoryChecks(). Like:
> 
>    bytes = ((bytes + ADDRESS_SIZE - 1) & ~(ADDRESS_SIZE - 1));
> 
> Then it will throw an IllegalArgumentException if the result is outside
> the size_t range. And in the native code we can just assert that the
> `size' argument is already aligned:
> 
>    assert(is_aligned(sz, HeapWordSize), "sz not aligned");

That seems quite reasonable.

Thanks,
David

> 
> Thanks,
> Nick
> 


More information about the core-libs-dev mailing list