2

I want to study Java again, because I leave it some years ago. Reading a book I had a problem understanding how Java allocate memory in heap and in stack.

This is what I've understood - I'll try to speak about it with examples.

class TestA {
    int a;

    void methodA(int b) {
        a = b;
    }

    int getA() {
        return a;
    }
}

This is a sample class to show different situation. And this is my main:

int b = 3;

TestA obj = new TestA();
obj.methodA(b);
obj.getA();

So what happen?


## BEGIN

STACK - take some memory for main function

HEAP - empty


## int b = 3

STACK - [take some memory for main function -> here we have b]

HEAP - [empty]


## TestA obj = new TestA()

STACK - [take some memory for main function -> here we have b and a reference to TestA]

HEAP - [take some memory for int a]


## obj.methodA(b);

STACK - [take some memory for main function -> here we have b and a reference to TestA]

HEAP - [take some memory for int a] AND [another memory for methodA]


## execute methodA(int b)

STACK - [take some memory for main function -> here we have b and a reference to TestA] AND [take memory for methodA() -> here we have b used in this function]

HEAP - [take some memory for int a] AND [another memory for methodA]


We have:

  • object AND instance field (primitive or not) in the heap
  • function and scope value in stack

Is it right?

trincot
  • 317,000
  • 35
  • 244
  • 286
Marco Pace
  • 3,820
  • 19
  • 38
  • 2
    All objects are allocated on the heap. Primitives are on the stack, along with the references to the objects. – Brian Roach Jan 10 '12 at 14:38
  • You can also track heap memory usage in order to confirm/deny your theories through experimentation. – jefflunt Jan 10 '12 at 14:41
  • 2
    Looks possible. But I have been doing Java for 13 years now and I really wonder why you care about it. Having a Garbage collector prevents you from focusing on this. – Snicolas Jan 10 '12 at 14:42
  • 3
    @BrianRoach: Not all primitives are on the stack. Only primitives that are variables in functions. Primitive data members of instances (or of classes) are part of the memory structure of the instance (or class) on the heap. – T.J. Crowder Jan 10 '12 at 14:44
  • @Snicolas: Indeed, one of the joys of Java, C#, JavaScript, et. al. is that we almost never have to care about this. Only really when it comes to tuning the JVM. – T.J. Crowder Jan 10 '12 at 14:45
  • Thanks to all, track the memory is a good idea! @snicolas: is for private pleasure ;-), I want to undestand why and how it works, not only use it – Marco Pace Jan 10 '12 at 14:45
  • @T.J.Crowder - I meant to imply that with the object part, but yes, I should have made that more clear. – Brian Roach Jan 10 '12 at 14:52
  • @T.J. Even if we cared about it, not much we can do anyhow. Also note that the whole "objects always allocated on the heap" hasn't been true for years by now. All production JVMs I'm aware of do EA and allocate objects on the stack if they can. – Voo Jan 10 '12 at 14:53
  • @Voo: Well, there are things we can do about it. If we're getting "out of heap" errors, for instance, with the Sun/Oracle JVM (at least) we can adjust how much heap space the JVM is allowed to have. Having an idea what contributes to the consumption of heap space is useful. Good point about JVM optimizations. – T.J. Crowder Jan 10 '12 at 14:56
  • @T.J. Sure, but increasing the heapspace doesn't really count as optimizing the used memory does it? ;) And sure we can also optimize the memory footprint, but that usually means using other objects or datastructures and not so much "allocate those objects on the stack we won't need them later". – Voo Jan 10 '12 at 15:03
  • @Voo: I didn't say anything about optimizing the memory used, just having an idea, in general terms, what is usually stored where. And I didn't say anything about trying to allocate things on the stack instead; are you confusing me with someone else? Thanks again for your other points. – T.J. Crowder Jan 10 '12 at 15:05
  • @T.J. Yeah confused myself a bit sorry ;-) – Voo Jan 10 '12 at 15:19

3 Answers3

2

At the outset, remember that the heap will also have the Class instance for your class (and several others).

Re:

## TestA obj = new TestA()

STACK - [take some memory for main function -> here we have b and a reference to TestA]

HEAP - [take some memory for int a]

a will be in the heap, not on the stack, as part of the memory allocated for the instance of TestA. b and obj are on the stack, allocated upon entry to main (er, I think that's when that happens; it could be that the JVM doesn't reserve stack space for them until it encounters the declarations in the program flow, but there we're getting into internals of the JVM). The heap also contains the instance of TestA. (Remember that obj, the variable, is quite distinct from what it points to [the instance of TestA]; each of those things takes memory.)

Also remember that the stack will contain the return addresses for the function calls. E.g., when main calls methodA, the address that the JVM should come back to when methodA returns is also on the stack.

Various stack structures will also be allocated for exception handling.

The above is mostly theoretical, mind. JVMs are welcome to do optimizations, and they do (HotSpot is a thoroughly optimizing JVM). @Voo points out, for instance, that JVMs may well put objects on the stack if they detect that they can (for instance, when the object instance is only used within the method and bytecode analysis by the JVM shows that it's impossible for there to be an outstanding reference to it when the method exits).

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Mmm, so when I declare an object it take memory for the method? Isn't it taked when I enter the method (so when I'm in obj.methodA(b);)? – Marco Pace Jan 10 '12 at 14:48
  • 1
    @MarcoPace: Let's say you have a method and it contains this line: `Foo f = new Foo();`. Two very different things happened there: `Foo f;` and `f = new Foo();`. The first one is a stack allocation; it happens upon entry to the method (at least, I believe it does; it could happen only when `Foo f` is encoutered in the program flow, but there we're getting into the internals of the JVM). The second one is a heap allocation, it happens when that line of code is executed. – T.J. Crowder Jan 10 '12 at 14:53
  • @MarcoPace: Note Voo's point about JVM optimizations, I've updated the answer to mention it. – T.J. Crowder Jan 10 '12 at 14:58
  • 2
    @T.J Assuming we're talking about the usual register machine with a stackpointer: The maximum amount of space necessary for the function is allocated at method entry, which is **NOT** identical to the sum of all stack variables. The JIT can share the space of several variables if their livetime doesn't overlap. Afaik the bytecode itself specifies the complete size of the variables (and the interpreter doesn't do the sharing optimization), as it makes debugging a good bit harder. – Voo Jan 10 '12 at 14:58
  • @Voo: Quite. I added a postscript about JVM optimizations, since they (well, HotSpot anyway; the only one I have any real experience with) do seriously cool things these days. – T.J. Crowder Jan 10 '12 at 15:00
1

Although Java is specified as a stack machine, it is not actually implemented that way in practice, so in real JVMs the size of the stack only changes on exit or entry to a method.

The heap is never empty -- it includes objects like Object.class among others which are instantiated by a bootstrap classloader before main starts.

All actions like new ClassName(...) allocate space in the heap* and all variable declarations (int x, Object ref) specify that space should be set aside on the stack when the enclosing function is entered**.

* - see caveat regarding optimizations at https://stackoverflow.com/a/8690592/20394
** - again optimizations can cause stack slots to be shared.

Community
  • 1
  • 1
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
0

By default all objects are allocated on the heap. However, there are compiler optimization that allow objects to be allocated on the stack (or avoid allocation all together). In particular escape analysis allows this in java 6.

ekj
  • 1,082
  • 2
  • 11
  • 22