I was reading What and where are the stack and heap?. One thing I am a bit fuzzy on is what happens to the stack after a method exits. Take this image for example:
The stack is cleared upon exiting the method, but what does that mean? Is the pointer at the stack just moved back to the start of the stack making it empty? I hope this is not too broad of a question. I am not really sure what is going on behind the scenes when the stack is cleared from exiting a method.
When a method is called, local variables are located on the stack.
Object references are also stored on the stack, corresponding objects are store in the heap.
The stack is just a region of memory, it has a start and end address.
The JVM (java virtual machine) has a register which points to the current top of the stack (stack pointer). If a new method is called, an offset will be added to the register to get new space on the stack.
When a method call is over, the stack pointer will be decreased by this offset, this frees the allocated space.
Local variables and other stuff (like return address, parameters...) may still on the stack and will be overwritten by next method call.
BTW: this is why java stored all objects in heap. When an object would be located on the stack, and you would return the reference which points to the stack, the object could be destroyed by next method call.
During execution of a function, all local variables are created in the stack. That means that the stack grows to make enough room for those variables.
When the function ends, all the local variables goes out of scope and the stack is rewinded. Nothing else needs to happen, no implicit zeroing memory. But :
semantically the variables go out of scope and can no longer be used
in the hard way, the stack pointer is rewinded, effectively freeing the memory : it will be useable by next function call
Above is not only true for functions but can be the same for any block of code since semantically the variables defined in the block go out of scope at end of block.
Is the pointer at the stack just moved back to the start of the stack making it empty?
the pointer at the stack is moved back to where it was before the function call. The stack would not be empty because it contains data that belongs to calls that brought the program to that point.
To illustrate: if func1 called func2 called func3 the stack will look something like this:
func1 args/local vars... | func2 args/local vars... | func3 args/local vars...
After func3 returns it will be:
func1 args/local vars... | func2 args/local vars...
A stack is just that, a stack of things, usually a stack of frames, with the frames containing parameters, local variables and instances of objects, and some other things depending on your operating system.
If you have instantiated objects on the stack, i.e. MyClass x and not MyClass * x = new MyClass(), then the object x will be torn down and its destructor called when the stack is rewound to the previous frame, which essentially just makes the current stack pointer(internal) point to the previous frame. In most native languages no memory will be cleared, etc.
Finally this is why you should initialise local variables(in most languages) as a call to the next function will setup a new frame which will most likely be in the same place as the previously rewound stack frame, so your local variables will contain garbage.
It might be useful for you to think about what your compiled code might look like at a machine (or, better for us humans, assembly) level. Consider this as a possible example in X86 Assembly:
When the method is called, arguments will either be passed in the registers or passed on the stack itself. Either way, the code calling the method will eventually:
call the_method
When this happens, the current instruction pointer is pushed onto the stack. The stack pointer is pointing at it. Now we're in the function:
the_method:
push ebp
mov ebp, esp
The current base pointer is preserved on the stack and the base pointer is then used to reference things in the stack (like passed in variables).
sub esp, 8
Next, 8 bytes (assuming two four byte integers are allocated) are allocated on the stack.
mov [ebp-4], 4
mov [ebp-8], 2
The local variables are assigned. This could actually be accomplished by simply pushing them but more likely there will be a sub involved. Fast forward to the end:
mov esp, ebp
pop ebp
ret
When this happens, the stack pointer is right back where it was when we started, pointing at the stored base pointer (saved frame pointer). This is popped back into EBP leaving ESP pointing at the return pointer which is then "popped" into EIP with the ret. Effectively, the stack has unwound. Even though the actual memory locations haven't changed for the two local variables, they are effectively above the stack (physically below in memory, but I think you get what I mean.)
Keep in mind the stack is a zone in memory assigned to a process.
In summary, when in your code you call a function (tipically in assembly language), you need to store in memory the registers you're going to use (it could vary if you're following another contract) because these registers could be overwriten by calls to another function (you'd need to the store return address, arguments, and a lot more, but let's omite that). To do that you decrease the stack pointer by that number of registers. Before to exit, you need to make sure you increase the stack pointer by that same number. You don't need to do anything more because the values you were storing are not needed anymore, they will be overwrited by the next function call.
In Java, references to objects are in the stack when the object itself is in the heap. If all the references to an object are removed from the stack, the garbage collector will remove the object from heap.
I hope my answer helps you. Also, check this.
Related
I have a function
public void f() {
int x = 72;
return;
}
So x is stored at possibly the address 0x9FFF.
When the function returns, what happens to the memory at that address? Is it still there? I.e is the value still 72? Or is it completely invalidated?
In C it is undefined behaviour.
In practice, if you were to try something like:
int *ptr;
void foo() {
bar();
printf("%d", *ptr);
}
void bar() {
int x = 72;
ptr = &x;
}
Then it's likely that in most implementations of C, foo() would print 72. This is because although the address referenced by ptr is available for reallocation, it's not likely to have been re-allocated yet, and nothing has overwritten that memory. The longer your program continues to run, initialising more local variables, and calling malloc(), the more likely it is that this memory address will be re-used, and the value will change.
However there's nothing in the C specification that says this must be the case - an implementation could zero that address as soon as it goes out of scope, or make the runtime panic when you try to read it, or, well, anything -- that's what "undefined" means.
As a programmer you should take care to avoid doing this. A lot of the time the bugs it would cause would be glaring, but some of the time you'll cause intermittent bugs, which are they hardest kind to track down.
In Java, while it's possible that the memory still contains 72 after it goes out of scope, there is literally no way to access it, so it does not affect the programmer. The only way it could be accessed in Java would be if there were an "official" reference to it, in which case it would not be marked for garbage collection, and isn't really out of scope.
Both the Java programming language and the Java virtual machine do not define what happens to the memory of a stack frame after the frame is popped. This is a low-level implementation detail that is masked by the higher level abstractions. In fact, the Java language and JVM bytecode make it impossible by design to retrieve already-deleted values from the stack (unlike C/C++).
In practice however, stack frames in Java will behave like stack frames in C. Growing the stack will bump its pointer (usually downward) and allocate space to store variables. Shrinking the stack will usually bump the pointer up and simply leave the old values in memory to rot without overwriting them. If you have low-level access to the JVM's stack memory region, this is the behavior you should expect to see.
Note that it is impossible in Java to do a trick like C where you attempt to read uninitialized stack variables:
static boolean firstTime = true;
public void f() {
int x;
if (firstTime) {
x = 72;
firstTime = false;
} else {
// Compile error: Variable 'x' may not have been initialized
System.out.println(x);
}
}
Other stack behaviors are possible in JVM implementations. For example, as frames are popped it is possible to unmap the 4 KiB virtual memory pages back to the operating system, which will actually erase the old values. Also on machine architectures such as the Mill, stack memory is treated specially so that growing the stack will always return a region filled with zero bytes, which saves the work of actually loading old values from memory.
Primitive types in Java are placed on the stack (into a local variables array of a frame). A new frame is created each time a method is invoked:
public void foo() {
int x = 72; // 'x' will be stored in the array of local variables of the frame
}
A frame is destroyed when its method invocation completes. At this moment all local variables and partial results might still reside on the stack, but they are abandoned and no longer available.
I'm not looking at the spec offhand, but I'm guessing that this isn't technically defined.
I actually tried something like that in C++ once and it was, in fact, 72 (or whatever I put there before the function call returned) if I remember correctly, so the machine didn't actually go through and write 0 to that location or something.
Some of this is an implementation detail, too. I implemented it in MIPS assembly language as well (I'll include a code sample if I can dig it up). Basically, when I needed registers, I'd just "grow" the stack by however many local variables I needed, store whatever the current values in the registers I needed were (so I could restore them later), and re-use the register. If that's the implementation, then the value could actually contain the value of a local variable in the caller. I don't think that that's exactly what Java's doing, though.
TL;DR It's an implementation detail, but in C at least odds are it won't overwrite the value in memory until it actually needs it. Java is much harder to predict.
How does Java generate a thread's stack trace?
Example:
Consider functionA calls functionB calls functionC calls functionD. If at any point in functionD getStackTraceElementArray is used it would give the array of functionCalls:
functionC->functionB->functionA
How does Java fill the StackTraceElement array at runtime? Assuming it fills the calling function when it reaches inside the called function, how does the JVM get the reference of the calling method inside the called method?
In the simplest case the stack trace is obtained from... the stack!
Each thread has a frame pointer (FP) register that points to the base address of a current stack frame. When a Java method is called, it first creates a new stack frame, i.e. it pushes a bunch of information onto the stack:
return address (where the method was called from);
current FP (which points to the caller frame);
method ID of the method being called;
pointers to the constant pool cache etc.
Then it updates FP to point to the newly created frame.
This way, you see, the frame pointers make a linked list: if I read a value pointed by FP, I get the base address of the previous frame.
Now notice that for each frame a method ID is always at the same offset from FP. So the stack walking is as easy as a while loop (written in pseudo-code):
address fp = currentThread.getFP();
while (fp != null) {
methodID m = (methodID) read_stack_at(fp + METHOD_OFFSET);
print_method(m);
fp = (address) read_stack_at(fp);
}
That's how it works inside JVM for interpreted methods. Compiled methods are a bit more complicated. They do not usually save a method reference on the stack. Instead there is a structure that maps addresses of compiled code to the metadata that contains compiled method info. But the idea of stack walking is still the same.
Let's say I have this code:
{
int var = 2;
// more code
}
What happens with 'var' after the code is executed and it is not used anymore? Is it deleted from memory or it stays there occupying memory, or something else?
Related to this, is it better to work with variables that way^, or to make some global variable and just change it's value?
Local variables live on the stack. If it's a reference to an object then only variable is on the stack.
Instance variables live on the heap because they belong to an object.
Also this post (Stack and heap memory in java) might be helpful.
To make a long story short, in java (and other JVM languages), you don't have to care about memory allocation and dealocation at all. You really shouldn't be worrying about it. Once you lose the reference to that variable (in this case, when the method call ends), the variable is effectively gone. Some indefinite amount of time after that, the Garbage collecting thread will notice that you can't possibly access that variable anymore, and free up the memory it was using.
See: Garbage Collection in Java.
if you are defining any variable as instance variable then that variable will be used by instance. and instance will be saved in Heap memory area.
Garbage collector will run periodically to clean non referenced object from memory.
but if that variable is defined inside any block or method then that will be stored Stack memory.
Java Stack memory is used for execution of a thread. They contain method specific values that are short-lived and references to other objects in the heap that are getting referred from the method. Stack memory is always referenced in LIFO (Last-In-First-Out) order. Whenever a method is invoked, a new block is created in the stack memory for the method to hold local primitive values and reference to other objects in the method. As soon as method ends, the block becomes unused and become available for next method.
Everything in Java is removed from memory when it is no longer referenced. It takes a lot of effort to cause true memory leaks in Java.
Java primitives like int, boolean, and char are put on the stack and removed from memory as soon as they leave scope. Java objects like String, arrays, or ArrayList are allocated on the heap (and referenced by the local variable on the stack). Objects are garbage collected (removed from memory) when there is no longer a reference to them.Static variables belong to a class and will be a reference an object as long as the class is loaded, which is usually the entire run time of the Java program. Statics are the closest thing Java has to global variables, but overuse or misuse of statics is actually a way to cause memory issues rather than solve them.
This looks like a silly question but I found it is hard to get it right. I have asked different people but couldn't get an ideal answer.
I want to know what happens after we call a normal method in Java (Provided in a single threaded environment).
My understanding is that:
All current stack variables are poped-up and stored somewhere (where?)
The current method call halts
The arguments of the newly called method are pushed to the stack
The method code runs
After the method finished running, the stack is again emptied and the old stack contents is again restored. (What happened if the function returns a value?).
Code continues with the calling method.
This is a very incomplete and possibly wrong answer. Can someone provide a more detailed description?
Many thanks.
No, that's actually fairly accurate:
1) current stack variables remain on the stack
2) The current method pauses
3) The arguments of the newly called method are pushed to the stack
4) The method code runs
5) After the method finished running, we pop the stack. The called method's stack variables are no longer valid - they no longer "exist" at this point.
6) We pass the return value (if any) to the caller
7) Code continues with the calling method. All it's stack variables remain intact.
==============================
ADDENDUM:
#Kevin -
Conceptually, I think you got it just about right. I clarified a few points, I hope that helps.
David Wallace's link is very good if you want to go in depth on how the JVM implements "method calling".
Here is a good overview on how "a stack" works. Any stack, calling any subroutine - not just Java: http://en.wikipedia.org/wiki/Call_stack
Finally, Marko Topolnik is correct. "The reality" is almost always complex enough that it doesn't lend itself to a simple, one-size-fits all answer. But I definitely think your understanding is good. At least at the 10,000 foot level.
IMHO...
For the interpreter, assuming an instance method, and taking some minor liberties:
The object pointer is used to reference the object, and from there the Class object.
The method pointer is located in the Class object. (The lookup to convert method name to method index was largely done when the class was loaded, so this is basically just an array index operation.)
Generally some sort of a "mark" is pushed onto the JVM stack. This would contain the caller's instruction pointer, and a pointer to the base of his stack. (Lots of different implementations here.)
The method's definition is consulted to see how many local vars are needed. That many blank elements are pushed onto the stack.
The object ("this") pointer is stored in local var 0, and any parms are stored in 1,2,3... as appropriate.
Control is transferred to the called method.
On return, the stack is popped down to the point where the call started, any return value is pushed onto the stack, and control is transferred back to the caller.
Compiled code is conceptually similar, only it uses the "C" stack, and interpreted code in a JITC environment will make use of both the JVM stack and the "C" stack.
I am learning java and right now
i am stuck at memory allocation of object's and local variables.
can any one illustrate or clear some of my doubts??
I read about Heap and Stack Memory for Object's instance
Variable's and Local Variable's. I have question whether a new
STACK is being created for each method?? or for each class of a
single stack is used by a whole class??
I had read that ONE STACK
is being created by every thread What is means
Thanks
Mahaveer
Every thread has it's own stack.
Whenever you use new, an object is created on the heap.
Local variables are stored on the stack. That includes primitives (such as int) and the references to any objects created. The actual objects themselves aren't created on the stack, as I mentioned when you use new they'll be created on the heap.
I have question that weather a new STACK is being created for each
method??
The same stack is being used when a method is called. A method will create it's own little section on the stack called a "stack frame" that's used to hold it's local variables.
It's just like a stack of plates, when a method is called a plate is added to the top of the stack (a stack frame), and when that method ends the plate is removed from the stack. All of that method's local variables will be destroyed with it, but the actual objects created with new won't.
The JVM's garbage collector will look after destroying objects on the heap (the one's created with new) when it sees you no longer need them.
Each thread has a private stack.
Each method has a private stack frame within that thread's stack.
Stacks are associated with thread in a one-to-one mapping. Stacks are absolutely not associated with methods and classes.
The way to reason about all this is that the local variables of a method are private to each invocation of that method.
Ofcourse, java garbage collector always takes care of the Heap, when it gets a chance to be executed, so it only looks for orphan objects and wipes them out, that's why NEW keyword in java always creates new objects on the Heap memory.