are objects in every stack-based-only VM allocated on heap [duplicate] - virtual-machine

Every time when I initiate a list in java, I will do
List<Integer> list = new LinkedList<>();
I assume that this will allocate the list on heap. Wonder if there's anyway that I could allocate the list on stack?

All objects, including their individual attributes, are stored on the heap.
All local variables, and their arguments, are stored on the stack because they contain primitive values or references.
However, in special cases, the java virtual machine may perform escape analysis and decide to allocate objects (including your LinkedList) on a stack, but this normally doesn't happen and isn't a major concern.
As a general rule, if you allocate an object on a stack you will get a copy of the object when you call a function that refers to it. In contrast, if you allocate an object on the heap, when you pass the pointer to the object you will get a copy of the pointer (which points to the very same object on the heap.)

It is theoretically possible for JVM implementations to allocate objects on the stack, using "escape analysis." If it can be determined that a reference to a created object never leaks off the stack, a JVM could allocate it on the stack instead of the heap. The benefit of this would be to reduce garbage collection overhead; when the stack frame is exited, that memory could be immediately reclaimed. It might also boost speed because of the locality of reference.
Starting in Java 7, escape analysis was introduced in the Oracle's HotSpot Java runtime. With this enhancement, HotSpot may choose not to allocate stack-local objects that aren't modified; rather than allocating them on the stack, it deletes the allocation altogether. While this stops short of stack allocation, it does demonstrate that such things are permissible runtime optimizations.
There is no way for the Java programmer to directly control this behavior, however. It's an optimization performed by the JIT compiler. I'm not sure if the language specification would permit this sort of optimization at compile-time. It might, but I haven't studied it.

Related

Why do programs have both stack and heap memory?

I am taking a course on programming languages right now and am having trouble understanding the difference between stack and heap variables and why both are needed in a program.
My textbook says this about "stack-dynamic variables":
Stack-dynamic variables are those whose storage bindings are created when
their declaration statements are elaborated, but whose types are statically
bound. Elaboration of such a declaration refers to the storage allocation and
binding process indicated by the declaration, which takes place when
execution reaches the code to which the declaration is attached. Therefore,
elaboration occurs during run time.
It also says this about "explicit heap-dynamic variables"
Explicit heap-dynamic variables are nameless (abstract) memory cells that
are allocated and deallocated by explicit run-time instructions written by the
programmer. These variables, which are allocated from and deallocated to the
heap, can only be referenced through pointer or reference variables. The heap
is a collection of storage cells whose organization is highly disorganized due
to the unpredictability of its use.
So my question is: why do we have both? From what I've read it seems that both stack variables and heap variables are allocated at runtime, so other than the fact that you need to use special keywords like new in C++ to create heap variables, I'm having trouble understanding the difference. I know that certain data structures like trees and linked lists are created with heap variables, but why is it not possible to create them using stack variables?

Clarification on stack & heap

I have read that stacks are using to manage function calls, where as heaps are used to store the objects that are allocating. What I understood that non primitive type objects will be stored in heap. I am confused on the following usages in the case of stack & heap:
1) Where the primitive data types, MACROS(#define), static objects, const, and extern?
2) Stacks manages the function calls, but I would like to know what info related to the functions are pushing to the stack?
3) I read somewhere that function related local objects are stored in Stack. So if any allocation of objects happens inside function, stack or heap is used? And if any primitive types objects are declared inside the function, where those are storing?
Sree.
Macros are resolved at compile time. Consts, globals, etc are part of the data segment - not the stack or the heap. https://en.wikipedia.org/wiki/Data_segment
Whenever you call a function it's parameters are pushed onto the stack.
All primitives, local variables, etc inside a function are allocated on the stack.
In simplified terms the compiler calculates how much memory each function needs (the total of all its variable usage). When the function is called that size is simply added to the stack and then it is subtracted in when it is finished.
At the most primitive level the only time heap memory is used (excluding libraries) is when you call malloc.
In the case of Objective-C pretty much every object is allocated dynamically on the heap whenever you call alloc or new. Objective-C is designed that way and heap allocation is normal. C and C++ tend to use the dynamic allocation on the heap less.
To understand what's really happening, you should build a small c program and generate assembly code of it.
What you will find there is the following:
Macros should be evaluated at compile time, not at runtime.
Constants, globals and static things are declared as constants and saved into the executable itself.
Primitive data variables or pointers are stored into CPU registers (extremely fast but limited in quantity) or stored in a stack frame in memory (more space but ca. 1000x slower). To understand stack frames, you should have a look at this explanation. Basically a stack frame is built by moving the stack pointer (which points to the memory location where new values are put onto the stack) down (the stack grows from big memory addresses to smaller ones) so there is some unused space on the stack, which can be locally used during a function.
If you call a function, the return address (the instruction pointer before the call + 1) is pushed onto the stack so when the function returns, the execution jumps to the return address by popping the return address from the stack and jumping to it.
If your function has a lot of arguments, the arguments 7, 8, etc... are stored on the stack before the function is called. All previous arguments are stored in registers
Unlike the stack, the heap space is assigned by the system and can only be accessed (to my knowledge) by interrupting the program and letting the operating system assign memory to the program (which will happen inside a malloc call). As objects are allocated ([NSObject alloc]) they can be found in the heap memory.
Summary
Primitive values and structs are stored next to return addresses of function calls on the stack
large memory allocations above a few bytes are made in heap space. This includes objects and arrays created with malloc.

What does "live in the heap" mean?

I'm learning Objectiv C, and I hear the term "live in the heap" constantly, from what I understand its some kind of unknown area that a pointer lives in, but trying to really put head around the exact term...like "we should make our property strong so it won't live in the heap. He said that since the property is private. I know it'ss a big difference It's pretty clear that we want to make sure that we want to count the reference to this object so the autorelease wont clean it (we want to "retain" it from what i know so far), but I want to make sure I understand the term since it's being use pretty often.
Appreciate it
There are three major memory areas used by C (and by extension, Objective C) programs for storing the data:
The static area
The automatic area (also known as "the stack"), and
The dynamic area (also known as "the heap").
When you allocate objects by sending their class a new or alloc message, the resultant object is allocated in the dynamic storage area, so the object is said to live in the heap. All Objective-C objects are like that (although the pointers that reference these objects may be in any of the three memory data areas). In contrast, primitive local variables and arrays "live" on the stack, while global primitive variables and arrays live in the static data storage.
Only the heap objects are reference counted, although you can allocate memory from the heap using malloc/calloc/realloc, in which case the allocation would not be reference-counted: your code would be responsible for deciding when to free the allocated dynamic memory.

What's the difference between abandoned memory and a memory leak?

Both are exactly the same thing, except that "abandoned memory" refers to a whole object graph leaked rather than just a single object. Right?
First, you need to understand the notion of a "memory object graph" or "application object graph" (or, simply, "object graph" as it applies to allocated buffers). In this case, "object" refers to any allocation in your application, be it an object or a simple malloc()ed buffer. The "graph" part if it is that any object can contain a reference to -- a pointer -- to other objects.
The "live object graph" of an application are all of the allocations that can be reached, directly or indirectly, from the various "roots" in the application. A "root" is something that, on its own, represents a live reference to an object, regardless of whether or not anything else explicitly references the root.
For example, global variables are roots; by referring to an object, a global variable, by definition, makes that object part of the app's live object graph. And, by implication, any objects that the object referred to by the global variable are also considered to be live; not leaked.
The same goes for the stack; any object referred to by any thread's live stack is, itself, considered live.
With this in mind, a leak and abandoned memory actually do have two distinct meanings.
Leak
A leak is a piece of memory for which there are no references to the allocation from any live object in the application's live object graph.
I.e. the memory is unreachable and, thus, there is no way that it can ever be referred to again (barring bugs). It is dead memory.
Note that if object A points to object B and object B points to A, but nothing in the live object graph points to either A or B, it is still a leak. If the B->A and A->B references are both retained references, you got yourself a retain cycle & a leak.
Abandoned Memory
Allocations that are in the app's live object graph but are no longer reachable due to application logic issues are considered abandoned, but not leaked.
For example, say you have a cache whose entries are instances of NSData that were downloaded from some URL where the URL contains a session ID in the URL (a common pattern) and that session ID + URL are used as the key to look up stuff in the cache. Now, say the user logs out, causing the session ID to be destroyed. If the cache isn't also pruned of all entries specific to that session ID, then all of those NSData objects will be abandoned, but not leaked as they can still be reached via the cache.
In reality, there is little use in making this strong of a distinction between the two save for that fixing either requires very different strategies.
Fixing a leak is to figure out where the extra retain came from (or where a missing call to free() might need to be inserted, in the case of a malloc() based leak). Since a detected leak cannot be reached from the live object graph, fixing a leak is really this straightforward.
Fixing abandoned memory can be considerably trickier for a couple of reasons.
First, the memory is still reachable from the live object graph. Thus, by definition, there is an algorithmic problem in your application that is keeping the memory alive. Finding and fixing that can often be much more difficult and potentially disruptive then fixing a mere leak.
Secondly, there might be non-zeroing non-retained weak references to the abandoned allocation. That is, if you figure out where to prune the strong references and make the allocation actually go away, that doesn't mean that your work is done; if there are any remaining non-zeroing weak references, they will now be dangling pointers and..... BOOM.
As Amit indicated, Heapshot Analysis is quite adept at finding both leaks, abandoned memory and -- quite important -- overall "Undesirable Memory Growth".
Not sure if there's a standard terminology, but there's also the possibility of having memory around which does have a reference, but will never be used. (The Heap Shot feature of the Leaks instrument can help track this down.) I call this "bloat" to distinguish it from a true leak. Both are wasted memory.
Abandoned memory are the memory leaks. Heapshot Analysis will help you to Find Undesirable Memory Growth. This is good article about that. http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/

How does it know where my value is in memory?

When I write a program and tell it int c=5, it puts the value 5 into a little bit of it's memory, but how does it remember which one? The only way I could think of would be to have another bit of memory to tell it, but then it would have to remember where it kept that as well, so how does it remember where everything is?
Your code gets compiled before execution, at that step your variable will be replaced by the actual reference of the space where the value will be stored.
This at least is the general principle. In reality it will be way more complecated, but still the same basic idea.
There are lots of good answers here, but they all seem to miss one important point that I think was the main thrust of the OP's question, so here goes. I'm talking about compiled languages like C++, interpreted ones are much more complex.
When compiling your program, the compiler examines your code to find all the variables. Some variables are going to be global (or static), and some are going to be local. For the static variables, it assigns them fixed memory addresses. These addresses are likely to be sequential, and they start at some specific value. Due to the segmentation of memory on most architectures (and the virtual memory mechanisms), every application can (potentially) use the same memory addresses. Thus, if we assume the memory space programs are allowed to use starts at 0 for our example, every program you compile will put the first global variable at location 0. If that variable was 4 bytes, the next one would be at location 4, etc. These won't conflict with other programs running on your system because they're actually being mapped to an arbitrary sequential section of memory at run time. This is why it can assign a fixed address at compile time without worrying about hitting other programs.
For local variables, instead of being assigned a fixed address, they're assigned a fixed address relative to the stack pointer (which is usually a register). When a function is called that allocates variables on the stack, the stack pointer is simply moved by the required number of bytes, creating a gap in the used bytes on the stack. All the local variables are assigned fixed offsets to the stack pointer that put them into that gap. Every time a local variable is used, the real memory address is calculated by adding the stack pointer and the offset (neglecting caching values in registers). When the function returns, the stack pointer is reset to the way it was before the function was called, thus the entire stack frame including local variables is free to be overwritten by the next function call.
read Variable (programming) - Memory allocation:
http://en.wikipedia.org/wiki/Variable_(programming)#Memory_allocation
here is the text from the link (if you don't want to actually go there, but you are missing all the links within the text):
The specifics of variable allocation
and the representation of their values
vary widely, both among programming
languages and among implementations of
a given language. Many language
implementations allocate space for
local variables, whose extent lasts
for a single function call on the call
stack, and whose memory is
automatically reclaimed when the
function returns. (More generally, in
name binding, the name of a variable
is bound to the address of some
particular block (contiguous sequence)
of bytes in memory, and operations on
the variable manipulate that block.
Referencing is more common for
variables whose values have large or
unknown sizes when the code is
compiled. Such variables reference the
location of the value instead of the
storing value itself, which is
allocated from a pool of memory called
the heap.
Bound variables have values. A value,
however, is an abstraction, an idea;
in implementation, a value is
represented by some data object, which
is stored somewhere in computer
memory. The program, or the runtime
environment, must set aside memory for
each data object and, since memory is
finite, ensure that this memory is
yielded for reuse when the object is
no longer needed to represent some
variable's value.
Objects allocated from the heap must
be reclaimed—especially when the
objects are no longer needed. In a
garbage-collected language (such as
C#, Java, and Lisp), the runtime
environment automatically reclaims
objects when extant variables can no
longer refer to them. In
non-garbage-collected languages, such
as C, the program (and the programmer)
must explicitly allocate memory, and
then later free it, to reclaim its
memory. Failure to do so leads to
memory leaks, in which the heap is
depleted as the program runs, risking
eventual failure from exhausting
available memory.
When a variable refers to a data
structure created dynamically, some of
its components may be only indirectly
accessed through the variable. In such
circumstances, garbage collectors (or
analogous program features in
languages that lack garbage
collectors) must deal with a case
where only a portion of the memory
reachable from the variable needs to
be reclaimed
There's a multi-step dance that turns c = 5 into machine instructions to update a location in memory.
The compiler generates code in two parts. There's the instruction part (load a register with the address of C; load a register with the literal 5; store). And there's a data allocation part (leave 4 bytes of room at offset 0 for a variable known as "C").
A "linking loader" has to put this stuff into memory in a way that the OS will be able to run it. The loader requests memory and the OS allocates some blocks of virtual memory. The OS also maps the virtual memory to physical memory through an unrelated set of management mechanisms.
The loader puts the data page into one place and instruction part into another place. Notice that the instructions use relative addresses (an offset of 0 into the data page). The loader provides the actual location of the data page so that the instructions can resolve the real address.
When the actual "store" instruction is executed, the OS has to see if the referenced data page is actually in physical memory. It may be in the swap file and have to get loaded into physical memory. The virtual address being used is translated to a physical address of memory locations.
It's built into the program.
Basically, when a program is compiled into machine language, it becomes a series of instructions. Some instructions have memory addresses built into them, and this is the "end of the chain", so to speak. The compiler decides where each variable will be and burns this information into the executable file. (Remember the compiler is a DIFFERENT program to the program you are writing; just concentrate on how your own program works for the moment.)
For example,
ADD [1A56], 15
might add 15 to the value at location 1A56. (This instruction would be encoded using some code that the processor understands, but I won't explain that.)
Now, other instructions let you use a "variable" memory address - a memory address that was itself loaded from some location. This is the basis of pointers in C. You certainly can't have an infinite chain of these, otherwise you would run out of memory.
I hope that clears things up.
I'm going to phrase my response in very basic terminology. Please don't be insulted, I'm just not sure how proficient you already are and want to provide an answer acceptable to someone who could be a total beginner.
You aren't actually that far off in your assumption. The program you run your code through, usually called a compiler (or interpreter, depending on the language), keeps track of all the variables you use. You can think of your variables as a series of bins, and the individual pieces of data are kept inside these bins. The bins have labels on them, and when you build your source code into a program you can run, all of the labels are carried forward. The compiler takes care of this for you, so when you run the program, the proper things are fetched from their respective bin.
The variables you use are just another layer of labels. This makes things easier for you to keep track of. The way the variables are stored internally may have very complex or cryptic labels on them, but all you need to worry about is how you are referring to them in your code. Stay consistent, use good variable names, and keep track of what you're doing with your variables and the compiler/interpreter takes care of handling the low level tasks associated with that. This is a very simple, basic case of variable usage with memory.
You should study pointers.
http://home.netcom.com/~tjensen/ptr/ch1x.htm
Reduced to the bare metal, a variable lookup either reduces to an address that is some statically known offset to a base pointer held in a register (the stack pointer), or it is a constant address (global variable).
In an interpreted language, one register if often reserved to hold a pointer to a data structure (the "environment") that associates variable names with their current values.
Computers ultimately only undertand on and off - which we conveniently abstract to binary. This language is the basest level and is called machine language. I'm not sure if this is folklore - but some programmers used to (or maybe still do) program directly in machine language. Typing or reading in binary would be very cumbersome, which is why hexadecimal is often used to abbreviate the actual binary.
Because most of us are not savants, machine language is abstracted into assembly language. Assemply is a very primitive language that directly controls memory. There are a very limited number of commands (push/pop/add/goto), but these ultimately accomplish everything that is programmed. Different machine architectures have different versions of assembly, but the gist is that there are a few dozen key memory registers (physically in the CPU) - in a x86 architecture they are EAX, EBX, ECX, EDX, ... These contain data or pointers that the CPU uses to figure out what to do next. The CPU can only do 1 thing at a time and it uses these registers to figure out what to do next. Computers seem to be able to do lots of things simultaneously because the CPU can process these instructions very quickly - (millions/billions instructions per second). Of course, multi-core processors complicate things, but let's not go there...
Because most of us are not smart or accurate enough to program in assembly where you can easily crash the system, assembly is further abstracted into a 3rd generation language (3GL) - this is your C/C++/C#/Java etc... When you tell one of these languages to put the integer value 5 in a variable, your instructions are stored in text; the assembler compiles your text into an assembly file (executable); when the program is executed, the program and its instructions are queued by the CPU, when it is show time for that specific line of code, it gets read in the the CPU register and processed.
The 'not smart enough' comments about the languages are a bit tongue-in-cheek. Theoretically, the further you get away from zeros and ones to plain human language, the more quickly and efficiently you should be able to produce code.
There is an important flaw here that a few people make, which is assuming that all variables are stored in memory. Well, unless you count the CPU registers as memory, then this won't be completely right. Some compilers will optimize the generated code and if they can keep a variable stored in a register then some compilers will make use of this!
Then, of course, there's the complex matter of heap and stack memory. Local variables can be located in both! The preferred location would be in the stack, which is accessed way more often than the heap. This is the case for almost all local variables. Global variables are often part of the data segment of the final executable and tend to become part of the heap, although you can't release these global memory areas. But the heap is often used for on-the-fly allocations of new memory blocks, by allocating memory for them.
But with Global variables, the code will know exactly where they are and thus write their exact location in the code. (Well, their location from the beginning of the data segment anyways.) Register variables are located in the CPU and the compiler knows exactly which register, which is also just told to the code. Stack variables are located at an offset from the current stack pointer. This stack pointer will increase and decrease all the time, depending on the number of levels of procedures calling other procedures.
Only heap values are complex. When the application needs to store data on the heap, it needs a second variable to store it's address, otherwise it could lose track. This second variable is called a pointer and is located as global data or as part of the stack. (Or, on rare occasions, in the CPU registers.)
Oh, it's even a bit more complex than this, but already I can see some eyes rolling due to this information overkill. :-)
Think of memory as a drawer into which you decide how to devide it according to your spontaneous needs.
When you declare a variable of type integer or any other type, the compiler or interpreter (whichever) allocates a memory address in its Data Segment (DS register in assembler) and reserves a certain amount of following addresses depending on your type's length in bit.
As per your question, an integer is 32 bits long, so, from one given address, let's say D003F8AC, the 32 bits following this address will be reserved for your declared integer.
On compile time, whereever you reference your variable, the generated assembler code will replace it with its DS address. So, when you get the value of your variable C, the processor queries the address D003F8AC and retrieves it.
Hope this helps, since you already have much answers. :-)