Stack and heap:
Stack
A stack is simply a specific range of memory that every program starts with. Each program has a stack, and when this programming is started, the CPU actually stores a pointer to 1. where is the "top" of the stack. When a function is called, the code (created by the compiler) writes the values (copies of the parameters, as well as the return address of the code that calls the function) to the point in memory that this stack pointer (SP) refers to. He then modifies the SP to indicate a little further, to the point after the parameters.
When your function returns, it writes the return value to the point in memory that SP points to, and then translates the code execution back into the code that calls this function. This code then copies the return value from the SP location and reduces the SP.
This area is called the stack because the program copies values to it when: 1. you declare local variables or 2. you call functions with parameters.
And then it pushes the parameters and local variables when returning from the function.
(This is how it works in theory. In practice, the compiler instead writes instructions for copying the values to the CPU registers instead, as well as the return value).
heap
The heap simply refers to all other memory that is allocated by the program, usually with a system call (brk on linux) (called malloc in C). A program can have many blocks of memory that it asked the operating system to allocate for it. These pieces of memory (in general) are called heaps.
In java:
when you use the 'new' keyword, what it does returns a pointer to some memory that it asked the operating system to give.
when you declare a variable not using the new one, what the compiled code will do is simply use the existing memory at the top of the stack's memory area, and then change the stack pointer.
When you use a pointer variable and assign it an object created using new ExampleObject (), you are actually doing both things. In this case, a pointer (reference) will be created at the location of the stack pointer. Then the stack pointer moves (it is added to 8 bytes, the size of the pointer value), then the new () function will receive a new memory link from the heap area, and then the value of this link will be copied to the local pointer variable.
In practice, a language such as Java, when it runs the program, starts with a specific stack of a certain size and a certain amount of memory (called heap) already allocated to it by the operating system, and will request more memory when it runs through space
It would be useful to see how processors work, in particular, how they have registers in which values are stored, and one of them is a stack pointer. Just like they do additions and subtractions. This is important because they do not (usually), for example, when adding, add the number from the reference address in memory to the number at another reference address. If you look at Assembly instructions (similar to java bytecode), what do they do more often:
For example, the function int addnum (int a, int b) {return a + b;} a. Load the number from the SP, that is, where the SP indicates, into register 1
b. Load the number from when the SP points (SP-1) to register 2
with. Call Add a CPU command that stores the result in register R3 d. Copy the value of R3 to SP + 1
What might look like
The code call is as follows: (note that these are compiled examples of CPU instructions - they are different for each processor, and Java has its own bytecode, which is similar. I just use, for example, STORESP => write to stack, LOADSP => loading from stack pointer)
int x; x = addnum(9,6); INCSP +1
Then the function itself
LOADSP,0,R1
Then the calling function again: Saves the result to x (copy of SP-2) (up to SP-3)
LOADSP,-2,R1 STORESP,R1,-3
Now the function call is completed. So throw away the space allocated on the stack for a and b and the return value (Decreasing SP by 3)
ADDSP -3
And now the result is in 'x'
Of course, this is much simplified and inaccurate, but this is just an example to help understand.
But if you can see how these low-level things work, just do something basic, for example, add two numbers, then this will help you understand the "where" and "how" parameters in the functions, and exactly how important the concept of the stack is
Good luck.