1

So the C language has a realloc() procedure that can be used to grow allocated [edit] memory in-place.

Does the equivalent concept exist for the JVM/Java? Either for Arrays or nio.Buffers? I don't mind whether this is part of the JDK or as an external library e.g. sun.unsafe.

Luciano
  • 2,388
  • 1
  • 22
  • 33
  • 2
    AFAIK, `realloc` allocates a new chunk of memory, and copies the contents there, then frees the original (although it claims that it might be able to grow it IF there so happens to be memory free behind it... undoubtably a rare case). `ArrayList` does exactly this, but transparent (ie, it will grow automatically when needed). – john16384 May 25 '19 at 15:21
  • @john16384 doing a copy of the array internally via `System::arrayCopy`; but otherwise exactly correct – Eugene May 27 '19 at 09:01
  • I'm specifically interested in the ability to grow the existing block, rather than 'copying it over'. Where can I find evidence to this effect @john16384 you say 'undoubtedly a rare case' - on what are you basing that? Perhaps this question should be titled "is it possible to grow existing allocations in JVM heap" to make this clearer. – Luciano May 27 '19 at 11:43
  • A JVM might do something like that internally, but from your Java code, you have no control over this in any way. You can't take a `byte[]` and ask for a larger one, you can only create a new one. As for me claiming that growing an array in C is a rare case -- memory gets fragmented, you have some control over this if you write your own allocation strategy for your C program, however, with many allocations happening, the chances of the correct area not being used already are slim. – john16384 May 28 '19 at 07:20

1 Answers1

3

First of all, the C function realloc is not a tool that can grow arrays, but rather, memory previously allocated via malloc, calloc, or realloc. In contrast, C arrays may reside on the stack or the static memory area and may even be embedded in a larger structure.

Then, the function has the semantics of invalidating the original pointer like free does and returning a new pointer. So if you have copies of the pointer flying around, it’s your duty of replacing all occurrences with the new pointer.

Of course, Java does not support invalidating references. Guaranteeing the validity of every non-null object reference, is the fundamental property of Java’s memory management.

So if you want the equivalent of C’s realloc, you’d have to use pointers and not arrays. Then sun.misc.Unsafe has all related operations

  • public long allocateMemory(long bytes)
  • public long reallocateMemory(long address, long bytes)
  • public void freeMemory(long address)
  • public float getXyz(long address)¹
  • public void putXyz(long address, xyz x)¹

¹ where “xyz” stands for a primitive type

If you want to resize an array, use

array = Arrays.copyOf(array, newSize);

this will not invalidate old references, so if you fail to replace all references to the old array, code using these old references will access the old array.

But if array is the only reference to the particular array or your code provenly replaces all existing references, a JVM may in theory enable an in-place resizing operation instead of copying the contents, see also Does Java JIT cheat when running JDK code?

But checking the necessary preconditions might be more expensive than copying the array contents. The only scenario where I can imagine an applicability, would be if the array was the last object allocated by the same thread, so it could be proven that the reference did not escape yet and there’s no object behind the array within the allocation space.

For a JVM having such an optimization, you may get the benefit automatically when repeatedly adding to an ArrayList, as that class ensures that it is the only holder of the reference to its internal array and it uses Arrays.copyOf internally for resizing.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • I've adjusted the OP as per your comments to reflect `realloc` doesn't operate on arrays. Thank you for the comprehensive answer. – Luciano May 30 '19 at 15:08