0

When we use a dynamic array in Java like a = new int[n], n is a argument passed in to the method, can Java use escape analysis and allocate this dynamic length array on the the stack instead of the heap? And can c do that? I mean can C allocate a dynamic length array on the stack or does it have to be on the stack? Is this where Java is better than C?

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
zhihaofeng
  • 35
  • 3
  • Correct me if I am wrong, I think in java the array object is always on the heap, and the reference variable is on stack. In C you can use malloc/calloc feature to allocate memory dynamically. – Yeou Jan 09 '20 at 09:02
  • I'm thinking , in jvm , jvm writes its own assembly code , it should have the ablity to generate a dynamic length array on the stack . i'm wondering if jvm actually do it – zhihaofeng Jan 09 '20 at 09:15
  • The stack size is typically rather small. It should NOT allocate on the stack. What makes you think that allocating on the stack would be better anyway? – ChrisMM Jan 09 '20 at 09:34
  • i mean isn't it nice if i want to new int[n] in a method , when n is really small ,like when n is 3 ,and java directly allocate this array on the stack , the array space can directly replaced after method ends and without gc, right? isn't it really nice ? i'm wondering if java would do that – zhihaofeng Jan 09 '20 at 09:41
  • i always thought it would be nice if one can allocate dynamic length array on the stack , jvm writes its assembly on the runtime ,can't it do that ? – zhihaofeng Jan 09 '20 at 09:43
  • Java uses JIT now days, so it is still compiled, and has to be generic enough. It might be able to allocate small constant sized arrays on the stack (you would have to look at how the JIT works to know), but then if you're using constant sized arrays, C always allocates on the stack. – ChrisMM Jan 09 '20 at 09:49
  • The JVM could check each allocation to determine if it should be stack or heap, but the over head in this would probably out weigh the dynamic allocation anyway. – ChrisMM Jan 09 '20 at 09:51
  • so if i allocate a dynamic length array , it would always be on the heap ? – zhihaofeng Jan 09 '20 at 09:57
  • Answering what a current JVM actually **does** requires quite in-depth knowledge of them, which is rather rare. Knowing what they *could* do is more readily available knowledge. A well-tuned JVM *could* even get rid of the array allocation entirely for small arrays and treat the entries as independent variables if the array doesn't escape. Does any current JVM actually **do** that? I have no idea ... – Joachim Sauer Jan 09 '20 at 10:45
  • 1
    The C standard supports dynamically sized arrays on the stack (resp. “automatic storage”) since C99; some compilers needed some time to implement this, but I suppose, nowadays, the answer is, yes, C can do that. The “stack allocation in Java” is a tenacious myth, a misunderstanding about what [*Scalar Replacement*](https://shipilev.net/jvm/anatomy-quarks/18-scalar-replacement/) is about. Technically, a JVM could make array allocations on the stack possible, but since that would have no advantage, it doesn’t happen. Look at [Andrei Pangin’s answer](https://stackoverflow.com/a/59662946/2711488) – Holger Jan 09 '20 at 11:30

2 Answers2

2

Theoretically Java can decide during runtime, whether to allocate on stack (based on Escape Analysis and if required allocation is below certain threshold) or to allocate on the heap.

However this is theoretical. To check if your JVM does this optimization for non constant values you can follow the test proposed in the following SO answer for another question on Escape Analysis in Java.

Amir Kirsh
  • 12,564
  • 41
  • 74
1
  1. HotSpot JVM does not do "on stack allocation" at all. Instead, it has Scalar Replacement optimization.
  2. HotSpot JVM can apply scalar replacement to arrays, but only if the length is a constant not larger than EliminateAllocationArraySizeLimit (equal to 64 by default), see escape.cpp:
    if (call->is_AllocateArray()) {
      if (!cik->is_array_klass()) { // StressReflectiveCode
        es = PointsToNode::GlobalEscape;
      } else {
        int length = call->in(AllocateNode::ALength)->find_int_con(-1);
        if (length < 0 || length > EliminateAllocationArraySizeLimit) {
          // Not scalar replaceable if the length is not constant or too big.
          scalar_replaceable = false;
        }
      }
apangin
  • 92,924
  • 10
  • 193
  • 247
  • I suppose, since the scalar replacement is about the variables being actually used, it could work for an array with dynamic size when only certain fixed index elements are used, but that doesn’t look like a scenario happening often in practice (and would require de-optimization when the dynamic size is smaller than the largest used index). – Holger Jan 09 '20 at 11:29