BIG
DATA

JAVA

STACK AND HEAP IN JAVA

Read more about »
  • Java 9 features
  • Read about Hadoop
  • Read about Storm
  • Read about Storm
 

Lets understand concept of stack and heap before we proceed with other advance topics of OOP.

The Stack

What is the stack? It's a special region of your computer's memory that stores temporary variables created by each function (including the main() function). The stack is a "FILO" (first in, last out) data structure, that is managed and optimized by the CPU quite closely. Every time a function declares a new variable, it is "pushed" onto the stack. Then every time a function exits, all of the variables pushed onto the stack by that function, are freed (that is to say, they are deleted). Once a stack variable is freed, that region of memory becomes available for other stack variables.

When you call a function the arguments to that function plus some other overhead is put on the stack. Some info (such as where to go on return) is also stored there. When you declare a variable inside your function, that variable is also allocated on the stack.

stack

Deallocating the stack is pretty simple because you always deallocate in the reverse order in which you allocate. Stack stuff is added as you enter functions, the corresponding data is removed as you exit them. This means that you tend to stay within a small region of the stack unless you call lots of functions that call lots of other functions (or create a recursive solution).

Another feature of the stack to keep in mind, is that there is a limit (varies with OS) on the size of variables that can be store on the stack. This is not the case for variables allocated on the heap.

To summarize the stack:

  • Stored in computer RAM just like the heap.
  • Variables created on the stack will go out of scope and automatically deallocate.
  • stack variables only exist while the function that created them, is running
  • Much faster to allocate in comparison to variables on the heap.
  • Implemented with an actual stack data structure.
  • Stores local data, return addresses, used for parameter passing
  • Can have a stack overflow when too much of the stack is used. (mostly from infinite (or too much) recursion, very large allocations)


The Heap

The heap is memory set aside for dynamic allocation. Unlike the stack, there's no enforced pattern to the allocation and deallocation of blocks from the heap; you can allocate a block at any time and free it at any time. This makes it much more complex to keep track of which parts of the heap are allocated or free at any given time.

Each thread gets a stack, while there's typically only one heap for the application.

To summarize the heap:

  • Stored in computer RAM just like the stack.
  • Variables on the heap must be destroyed manually and never fall out of scope.
  • Slower to allocate in comparison to variables on the stack.
  • Can have allocation failures if too big of a buffer is requested to be allocated.
  • Responsible for memory leaks.


Questions on stack and heap

To what extent are they controlled by the OS or language runtime? The OS allocates the stack for each system-level thread when the thread is created. Typically the OS is called by the language runtime to allocate the heap for the application.

What is their scope? The stack is attached to a thread, so when the thread exits the stack is reclaimed. The heap is typically allocated at application startup by the runtime, and is reclaimed when the application (technically process) exits.

What determines the size of each of them? The size of the stack is set when a thread is created. The size of the heap is set on application startup, but can grow as space is needed (the allocator requests more memory from the operating system).

What makes one faster? The stack is faster because the access pattern makes it trivial to allocate and deallocate memory from it (a pointer/integer is simply incremented or decremented), while the heap has much more complex bookkeeping involved in an allocation or free. Also, each byte in the stack tends to be reused very frequently which means it tends to be mapped to the processor's cache, making it very fast. Another performance hit for the heap is that the heap, being mostly a global resource, typically has to be multi-threading safe, i.e. each allocation and deallocation needs to be - typically - synchronized with "all" other heap accesses in the program.



The Stack and the Heap: where things live

Objects are born and objects die. You're in charge of an object's lifecycle. Before we can understand what really happens when you create an object, we need to learn more about where everything lives and for how long. That means we need to learn more about the Stack and the Heap.

I will be explaining about stack and heap using Java. In java, we(programmers) care about two areas of memory-the one where objects live (the heap), and the one where method invocations and local variables live(the stack). When a JVM starts up, it gets a chunk of memory from the underlying OS, and uses it to run your Java program.

The two kinds of variables we care about now are instance variables and local variables. Local variables are also known as stack variables, which is a big clue for where they live.

[Note]:Instance variables are declared Inside a class but not Inside a method. They represent the "fields" that each Individual object has (which can be filled with different values for each Instance of the class). Instance variables live inside the object they belong to.

public class Car{
	int mileage;
}

Above code says, Every Car has a "mileage" instance variable.


Local variables are declared Inside a method, including method parameters, They're temporary,and live only as long as the method is on the stack (in other words, as long as the method has not reached the closing curly brace).
public void someMethod(int x){
	int i = x + 10;
	boolean bln = true;
}

Here parameter 'x' and the variables 'i' and 'bln' are all local variables.

Methods are stacked
methodstack

When you call a method, the method lands on the top of a call stack. That new thing that's actually pushed onto the stack is the stack frame, and it holds the state of the method including which line of code is executing, and the values of all local variables.

The method at the top of the slack is always the currently-running method for that stack. A method stays on the stack until the method hits its closing curly brace (which means the method's done). If method foo() calls method bar(), method bar() is stacked on top of method foo().

[Note]: Above picture and releated context are taken from Head First Java Book. I strongly recommend to read this book. You can buy here.

Local variables that are objects

Remember, a non-primitive variable holds a reference to an object, not the object itself. You already know where objects live--on the heap. It doesn't matter where they're declared or created. If the local variable is a reference to an object, only the variable (the reference) goes on the stack. The object itself still goes in the heap.

public class StackRef {
	public void foof(){
		barf();
	}
	
	public void barf() {
		Duck d = Dew Duck (24);
	}
}
objectstack
Instance variables

where do Instance variables live?
instance variable stack When you say new Cellphone() ,Java has to make space on the Heap for that CellPhone. But how much space? Enough for the object, which means enough to house all of the object'S instance variables. That's right,Instance variables live on the heap, inside the object they belong to.

Remember that the values of an object's instance variables live inside the object. If the instance variables are all primitives, Java makes space for the instance variables based on the primitive type. An int needs 32 bits, a long 64 bits, etc. Java doesn't care about the value inside primitive variables; the bit-size of an int variable is the same (32 bits) whether the value of the int is 32,000,000 or 32.

But what if the instance variables are objects?
What if CellPhone HAS-A Antenna? In other words, CellPhone has a reference variable of type Antenna.When the new object has instance variables that are object references rather than primitives, the real question is: does the object need space for all of the objects it holds references to? The answer is, not exactly. No matter what,Java has to make space for the instance variable values. But remember that a reference variable value is not the whole object, but merely a remote control to the object. So if CellPhone has an instance variable declared as the non-primitive type Antenna, Java makes space within the CellPhone object only for the Antenna's remote control (i.e. reference variable) but not the Antenna object.

Well then when does the Antenna object get space on the Heap? First we have to find out when the Antenna object itself is created. That depends on the instance variable declaration. If the instance variable is declared but no object is assigned to it, then only the space for the reference variable (the remote control) is created.

private Antenna ant;
instancevarstack2

No actual Antenna object is made on the heap unless or until the reference variable is assigned a new Antenna object.

private Antenna ant = new Antenna();
instancevarstack3

Object creation

Now that you know where variables and objects live, we can discuss about Object creation. There are 3 steps in creating: declare a reference variable, create an object and assign the object to the reference.

Car myCar = new Car();

This one line of code has all three steps for creating an object. Lets break it and analyze it.

Car myCar
 = 
new Car()

[1] Declare a reference variable: When you write "Car myCar", you are actually declaring a reference variable.
[2] Create an object: When you write "new Car()", you are creating a new Car object.
[3] Assign the object to the reference: When you write "=", you are assigning new car object to "myCar" reference variable.

[Note]: When we were creating new Car object, Are we calling method named Car()?. it looks like we are calling a method named Car() because of the parantheses. But NO, we are calling the Car constructor.

A constructor does look and feel a lot like a method, but it's not a method. It is the code that runs when you say new. In other words, the code that runs when you create an object.

Lets learn all about constructor in the next chapter.

But before we sign off from this chapter lets learn one more concept: Boxing and Unboxing



Boxing and Unboxing

Java uses primitive types such as int, char etc to hold basic data types.Eventhough there are performance benefits for using primitive types, there will be situation where you will need an object representation. Like while using data structures, Java operates on objects. Hence you are forced not to use primitive types. To handle these issues java has type wrappers which provide classes that encapsulate a primitive type within an object. Like:

Character (char myChar)
Integer (int myInt)

Integer: Encapsulates primitive type int within object.

A process by which primitive type is encapsulated or so called boxed into its respective type wrapper is called as Boxing or Autoboxing.
Unboxing or Auto-Unboxing is a process by which the value of object is automaticallhy extracted from a type wrapper.

So the automatic conversion of primitive data types into its equivalent Wrapper type is known as boxing and opposite operation is known as unboxing.

public void Method1(){
	int i = 1;
	object O = i;  //Boxing
	int j = (int)O;  //Unboxing
}
boxing

Thats all about Stack and Heap. Now go take a break and later we will start off with one of the main concept: constructor. Keep studying, Facebook, Google, Amazon, LinkedIn will be knocking at your door with exciting job offers and perks and all you have to do is open the door. Happy Job hunting.