The proper understanding of concepts in this tutorial is a prerequisite to understand the next few tutorials. So you are advised to give some extra attention to this tutorial.
If you know c or c++, you know that you have to manage memory yourself. In java the memory is managed by itself and needs no explicit intervention of the programmer.
If java is your first programming language you may find it somehow confusing. So let us discuss memory management in great detail.
Although memory is a shared system resource, processes(programs) view it as nothing more than a linear container and believe they have exclusive access to all memory. Memory management is the method through which an operating system, such as Microsoft Windows, produces and preserves the appearance that memory is accessible to a particular process(program).
When using a computer to “compute,” you ask for resources, and one of those is memory (also known as RAM), which the computer(in strictly technical terms it is the kernel) exposes for programmers to directly manage. The computer (kernel) will gladly give you memory, after you request it, to the best of its ability. You must, however, keep in mind that other programs may also require some of it, as your program. In order to allow others to utilize the memory that you no longer require, you kindly inform the computer(kernel). While programming you must regularly request memory, thus it is nice to release it when not needed. This is where management enters the picture; you try to be smart about how to use it, as it is scarce in nature. For example, suppose you request 16 bytes of memory to store four integers, but after a while, you no longer require that chunk of memory. Then you should return it to the computer so that it can be assigned to someone else (or maybe even yourself in some other part of the program). Also, you don’t want to free things too soon, even before you’ve finished computing with them – this could cause unexpected problems with your program.
No matter what programming language you use, memory is a vital resource. As a result, it is critical that memory be managed thoroughly and without leaks. Memory allocation and deallocation is a critical task that requires great care and consideration.
What is Memory Management In Java?
Memory management in Java refers to the process of allocating working memory space to new objects and removing unreferenced objects to make room for those new object allocations. In some programming languages, for example, C the programmer has direct memory access and allocates memory in his code. But this creates a lot of scope for memory leaks. In Java, the JVM and to be specific the Garbage Collector plays the role of managing memory, relieving the programmer of this mundane task. In general, developers do not have to deal with memory handling in Java directly because the Garbage Collector handles memory deallocation automatically.
What is a memory leak?
Memory leaks in Java occur when no longer used objects are present in the application and the garbage collector is unable to remove them from memory, causing them to remain there unnecessarily. Furthermore, memory leaks are uncommon because they can block memory resources and degrade system performance over time. If not addressed in a timely manner, the application will consume increasing amounts of resources, eventually leading to a fatal OutOfMemoryError. Memory leaks in Java are frequently regarded as indicators of poorly written programs. Java resource leaks can involve a small number of memory resources that may not be noticeable to you. When your application returns a java.lang.OutOfMemoryError, you should suspect a Memory Leak.
Why Learn Java Memory Management?
As previously stated, Java manages memory on its own and no special intervention by programmers is required. Garbage Collector is in charge of removing objects from the application’s working memory(RAM) that are no longer in use. So, why should Java programmers learn about automatic memory management?
Garbage Collector, despite being said to be automatic, does not guarantee the deallocation of memory/objects that are still referenced. Unknowingly, programmers leave objects referenced, even after their use is complete, resulting in memory leaks or other consequences that the Java Virtual Machine(JVM) cannot manage. To write efficient programs with no memory leaks, programmers should understand Java memory management. As a programmer, you must understand which objects are subject to automatic garbage collection and which are not. As a result, learning memory management is critical in order to write efficient and high-performance programs with a low chance of crashing.
Classification or Types of Java Memory Management
Working memory is an essential resource for any programming language. As a result, a better understanding of its management is critical.
The major concepts in Java Memory Management:
1) JVM Memory structure
2) Working of Garbage Collector.
Let us discuss them in more detail.
JVM Memory Structure
JVM defines various run-time data areas that are used during program execution. Some of the areas are created by the JVM, while others are created by threads in a program. The memory area created by JVM, is destroyed only when the JVM exits. Thread data areas are created during thread instantiation and destroyed when the thread exits.
JVM Memory Is Divided Into Multiple Parts:
Method Area
The method area is a logical part of the heap area that is created when the Virtual Machine boots up. The method area is reserved for method data, class structures, constructor field data, interfaces, and special methods in a class.
The Method area can be either fixed or dynamic, depending on the system configuration. It does not have to be contagious. Garbage collection is required in the heap, but the Method area, despite being a logical part of the heap area, may or may not be garbage collected.
Note: Though the method area is logically a part of the heap, it may or may not be garbage collected even if garbage collection is compulsory in the heap area.
Heap Area
Please give extra attention to this section. This is the most important segment of this tutorial and the next few.
The heap area is a shared runtime data area in which the actual objects (all class instances and arrays) are stored in memory. It is instantiated when the virtual machine boots up. The heap size can be dynamic or fixed, depending on the system configuration. Heap Memory allocated to the objects is reclaimed by the Garbage Collector. The heap’s maximum size is set to 64 Mb by default. When you use the new keyword, memory is allocated in the heap for an object.
A running Java Virtual Machine process always has only one Heap. The garbage collector clears the objects when the heap is full.
Series mySeries = new Series();
The preceding statement creates an object of the Series class, which is allocated to heap. In simple words, the newly created Series object resides in the heap.
A quick question to you? The object of type Series resides in the heap. Where does the variable mySeries reside?
Note: Garbage collection in the heap area is mandatory.
JVM Stack Area
Stack memory is a small area of memory allocated to variables with short lives, such as local variables and object reference variables(variables that are used to reference an object that is stored in the heap memory area). A stack is created at the same time when a thread is created. A given Java program has many stacks, and when multithreading is used, each thread has its own stack. Stack memory does not have to be contagious. Its size can be fixed or dynamic, and it can be determined independently when it is created. The variables stored in the stack have a level of visibility known as scope. A stack is a type of memory area, similar to how you keep one book on top of another. Heap is similar to random memory allocation.
Stack memory operates on the principle of First In Last Out, which means that local variables(variables declared in a method) are added to the stack memory in a top-down fashion, with the first local variable added to the stack being the first from the bottom and the last variable added being the first from the top. The scope of these variables is limited to the method by which they are defined. When that method is terminated, all variables defined in that method are erased from the stack, with the most recently added variable being the first to be erased.
Note: Whenever an object is created, it’s always stored in the heap space and stack memory contains the reference to it.
Let’s look at an example to see how objects are stored in heap memory. Look at the following class.
class someClass{
int a = 20; // instance variable in object which is in the heap
public void bar(){
Human human = new Human(); // an object in heap
int count = 10; // local variable | in stack
}
}
Variable a is an instance variable and it is of primitive data type, so it undoubtedly resides in the heap.
Now let us determine where the object of type Human and local variable count reside.
Human human = new Human();
int count = 10;
Now, the count is a variable that holds a primitive data type integer value; the count is added to the stack first as it is a method variable.
In Java, a Human is an object. The physical object(Human) is stored in heap memory. The new keyword (Human human = new Human()) allocates enough heap memory to store physical object memory. The name of the object reference variable which is “human” is then added to the stack, and a link (a pointer pointing from the reference variable to the physical object) is established between the object reference variable and the physical object.
The Human type object is stored in the heap.
The variable human is stored in the stack and it acts as a reference to the actual object stored in the heap.
- The value of the count is 10. But the value of humans is not a Human type object. Instead, the value of the human is an address where the actual Human object is stored. We will discuss it even more in the next tutorial. For now, just remember the following:
- When an object is created, heap space is used to store it, while stack space is used to store its reference and temporary variables.
- Heap is allocated during runtime, while the stack is allocated during compile time.
- The size of the stack is limited by the operating system, and heap memory content is retained until the program terminates.
The following picture demonstrates this.
Program Counter (PC) Registers
Every JVM thread that is created has a PC register associated with it. In the native method, the value of the program counter is undefined, whereas the non-native method has a Program Counter that stores the address of the JVM instructions currently being executed. It also stores the native pointer or the return address.
Native Method Stack
The Native Method stack is also referred to as the C stack. Native method stacks are written in languages other than Java. The native stack is accessed via the Java Native Interface (JNI). When a thread is created, it is given this type of memory. It, like other types, can be fixed or dynamic. The performance of the native stack is determined by the operating system.
Working as a Garbage Collector
Objects are allocated memory in the heap when a Java program runs. Garbage Collector makes every effort to maintain as much free working memory space as possible. Garbage Collection is only possible in the heap area of java memory. Because it is the only segment of the Java memory structure where Garbage Collection is possible, the Heap area is also known as the Garbage Collectable heap.
What is Java Garbage Collection?
Garbage collection is the process of removing unreferenced objects from memory. The garbage collector is controlled by the Java Virtual Machine (JVM), which decides when to run it. Garbage collection occurs whenever the JVM detects a lack of working memory resources. JVM also takes into account our request to perform garbage collection. However, JVM’s compliance with our request is not always guaranteed.
What are the criteria for an object to be eligible for garbage collection?
Garbage collection is available for all unreferenced objects in the Heap. But what causes a garbage collector to believe that an object is unreferenced or has not been referenced? Because Java runs multiple threads, all usable objects in the Heap are accessible from the stack frames of the threads that are running. Any object that cannot be reached by any thread is considered unreferenced and is subject to garbage collection.
Garbage Collection Process
The garbage collection process is managed by the Java Virtual Machine. It triggers the GC to deallocate memory occupied by unreferenced objects, easing the burden on programmers.
Other processes are paused while Garbage Collection is running. You can solve this problem by using several garbage-collector-based algorithms to improve the program’s performance. This is known as Garbage Collector tuning.
Another option is generational garbage collection. Objects are grouped according to how many clock cycles they have survived (age). The work of Garbage Collection is distributed in this manner.
The Following are the fundamental methods of garbage collection.
- Marking: The Garbage Collector identifies objects in working memory that is no longer used by the program.
- Normal Deletion: The garbage Collector removes objects that are no longer in use and frees up working memory space for other objects.
- Deletion with compacting: To improve the performance of memory allocation to newer program objects, all survived objects are moved to be together after Garbage Collection.
Managing the heap ensures that your application runs smoothly and eliminates the possibility of out-of-memory errors and system crashes. Understanding how memory is managed will assist you in writing memory-efficient optimized code.
We have discussed a lot of technical terms in this tutorial that you may or may not be familiar with. Just keep in mind that these things exist and you will more often than not come across them in the future when you are a bonafide developer. In this tutorial just focus on the heap part. Because it will help you understand the next tutorial.