Java Memory Allocation
Java Memory Allocation
Stack = Stack Memory in Java is used for static memory allocation and the
execution of a thread. It contains primitive values that are specific to a method and
references to objects that are in a heap, referred from the method.
When the method finishes execution, it’s corresponding stack frame is flushed, the flow
goes back to the calling method and space becomes available for the next method.
Apart from what we have discussed so far, following are some other features of stack
memory:
It grows and shrinks as new methods are called and returned respectively
Variables inside stack exist only as long as the method that created them is running
It's automatically allocated and deallocated when method finishes execution
If this memory is full, Java throws java.lang.StackOverFlowError
Access to this memory is fast when compared to heap memory
This memory is threadsafe as each thread operates in its own stack
Heap = Heap space in Java is used for dynamic memory allocation for Java objects
and JRE classes at the runtime. New objects are always created in heap space and the
references to this objects are stored in stack memory.
These objects have global access and can be accessed from anywhere in the application.
This memory model is further broken into smaller parts called generations, these are:
1. Young Generation – this is where all new objects are allocated and aged. A
minor Garbage collection occurs when this fills up
2. Old or Tenured Generation – this is where long surviving objects are stored.
When objects are stored in the Young Generation, a threshold for the object's
age is set and when that threshold is reached, the object is moved to the old
generation
3. Permanent Generation – this consists of JVM metadata for the runtime classes
and application methods
These different portions are also discussed in this article – Difference Between JVM,
JRE, and JDK.
We can always manipulate the size of heap memory as per our requirement. For more
information, visit this linked Baeldung article.
https://guru99.es/java-static-variable-methods/
5. Summary
From the name, it looks like Garbage Collection deals with finding and deleting the
garbage from memory. However, in reality, Garbage Collection tracks each and every
object available in the JVM heap space and removes unused ones.
In simple words, GC works in two simple steps known as Mark and Sweep:
Mark – it is where the garbage collector identifies which pieces of memory are
in use and which are not
Sweep – this step removes objects identified during the “mark” phase
Advantages:
Disadvantages:
Since JVM has to keep track of object reference creation/deletion, this activity
requires more CPU power besides the original application. It may affect the
performance of requests which required large memory
Programmers have no control over the scheduling of CPU time dedicated to
freeing objects that are no longer needed
Using some GC implementations might result in application stopping
unpredictably
Automatized memory management will not be as efficient as the proper manual
memory allocation/deallocation
3. GC Implementations
However, there was an excellent talk by Twitter engineers at QCon 2012 on the
performance of Serial Garbage Collector – which is a good way to understand this
collector better.
The Serial GC is the garbage collector of choice for most applications that do not have
small pause time requirements and run on client-style machines. To enable Serial
Garbage Collector, we can use the following argument:
t's the default GC of the JVM and sometimes called Throughput Collectors. Unlike
Serial Garbage Collector, this uses multiple threads for managing heap space. But it
also freezes other application threads while performing GC.
If we use this GC, we can specify maximum garbage collection threads and pause time,
throughput, and footprint (heap size).
The numbers of garbage collector threads can be controlled with the command-line
option -XX:ParallelGCThreads=<N>.
The maximum pause time goal (gap [in milliseconds] between two GC)is specified with
the command-line option -XX:MaxGCPauseMillis=<N>.
The maximum throughput target (measured regarding the time spent doing garbage
collection versus the time spent outside of garbage collection) is specified by the
command-line option -XX:GCTimeRatio=<N>.
The maximum heap footprint (the amount of heap memory that a program requires
while running) is specified using the option -Xmx<N>.
Simply put, applications using this type of GC respond slower on average but do not
stop responding to perform garbage collection.
A quick point to note here is that since this GC is concurrent, an invocation of explicit
garbage collection such as using System.gc() while the concurrent process is working,
will result in Concurrent Mode Failure / Interruption.
If more than 98% of the total time is spent in CMS garbage collection and less than 2%
of the heap is recovered, then an OutOfMemoryError is thrown by the CMS collector. If
necessary, this feature can be disabled by adding the option -XX:-UseGCOverheadLimit
to the command line.
This collector also has a mode knows as an incremental mode which is being deprecated
in Java SE 8 and may be removed in a future major release.
To enable the CMS Garbage Collector, we can use the following flag:
As of Java 9, the CMS garbage collector has been deprecated. Therefore, JVM prints a
warning message if we try to use it:
Difference Between JVM, JRE, and JDK
2. JVM
The JVM first interprets the bytecode. It then stores the class information in the memory
area. Finally, it executes the bytecode generated by the java compiler.
It is an abstract computing machine with its own instruction set and manipulates various
memory areas at runtime.
Class Loaders
Run-Time Data Areas
Execution Engine
Initial tasks of the JVM includes loading, verifying and linking the bytecode. Class
loaders handle these tasks.
The JVM defines various memory areas to execute a Java program. These are used
during runtime and are known as run-time data areas. Some of these areas are created on
the JVM start-up and destroyed when the JVM exits while some are created when a
thread is created and destroyed when a thread exits.
Method Area
Basically, method area is analogous to the storage area for compiled code. It stores
structures such as run-time constant pool, field and method data, the code for methods
and constructors as well as fully qualified class names. The JVM stores these structure
for each and every class.
The method area, also known as permanent generation space (PermGen), is created
when the JVM starts up. The memory for this area does not need to be contiguous. All
the JVM threads share this memory area.
Heap Area
The JVM allocates the memory for all the class instances and arrays from this area.
Garbage Collector (GC) reclaims the heap memory for objects. Basically, GC has three
phases to reclaim memory from objects viz. two minor GC and one major GC.
Eden Space – it's a part of Young Generation space. When we create an object, the
JVM allocates memory from this space
Survivor Space – it's also a part of Young Generation space. Survivor space contains
existing objects which have survived the minor GC phases of GC
Tenured Space – this is also known as the Old Generation space. It holds long surviving
objects. Basically, a threshold is set for Young Generation objects and when this
threshold is met, these objects are moved to tenured space.
JVM creates heap area as soon as it starts up. All the threads of the JVM share this area.
The memory for the heap area does not need to be contiguous.
Stack area
Stores data as frames and each frame stores local variables, partial results and nested
method calls. JVM creates the stack area whenever it creates a new thread. This area is
private for each thread.
Each entry in the stack is called Stack Frame or Activation record. Each frame contains
three parts:
Local Variable Array – contains all the local variables and parameters of the method
Operand Stack – used as a workspace for storing intermediate calculation's result
Frame Data – used to store partial results, return values for methods, and reference to
the Exception table which provides corresponding catch block information in case of
exceptions
The memory for the JVM stack does not need to be contiguous.
PC Registers
Each JVM thread has a separate PC Register which stores the address of the currently
executing instruction. If the currently executing instruction is a part of the native
method then this value is undefined.
Native methods are those which are written in languages other than Java.
JVM provides capabilities to call these native methods. Native method stacks are also
known as “C stacks”. They store the native method information. Whenever the native
methods are compiled into machine codes, they usually use a native method stack to
keep track of their state.
The JVM creates these stacks whenever it creates a new thread. And thus JVM threads
don't share this area.
Execution engine executes the instructions using information present in the memory
areas. It has three parts:
Interpreter
Once classloaders load and verify bytecode, the interpreter executes the bytecode line
by line. This execution is quite slow. The disadvantage of the interpreter is that when
one method is called multiple times, every time new interpretation is required.
JIT compiler compiles the bytecode of the often-called methods into native code at run-
time. Hence it is responsible for the optimization of the Java programs.
JVM automatically monitors which methods are being executed. Once a method
becomes eligible for JIT compilation, it is scheduled for compilation into machine code.
This method is then known as a hot method. This compilation into machine code
happens on a separate JVM thread.
As a result, it does not interrupt the execution of the current program. After compilation
into machine code, it runs faster.
Garbage Collector
Java takes care of memory management using Garbage Collection. It's a process of
looking at heap memory, identifying which objects are in use and which are not, and
finally deleting unused objects.
It acts as an interface between the Java code and the native (C/C++) libraries.
There are situations in which Java alone doesn't meet the needs for your application, for
example, implementing a platform-dependent feature.
In those cases, we can use JNI to enable the code running in the JVM to call.
Conversely, it enables native methods to call the code running in the JVM.
2.5. Native Libraries
These are platform specific libraries and contains the implementation of native methods.
3. JRE
We discussed the JVM in the above section. Here we will focus on the core classes and
support files.
We'll find bootstrap classes under jre/lib/. This path is also known as the bootstrap
classpath. It includes:
Bootstrap ClassLoader loads these classes when the JVM starts up.
We can find extension classes in jre/lib/extn/ which acts as a directory for extensions to
the Java platform. This path is also known as extension classpath.
It contains JavaFX runtime libraries in jfxrt.jar and locale data for java.text and java.util
packages in localedata.jar. Users can also add custom jars into this directory.
Java platform uses these property settings to maintain its configuration. Depending on
their usage they are located in different folders inside /jre/lib/. These include:
Apart from the above-mentioned files and classes, JRE also contains files for other
matters:
4. JDK
Java Development Kit (JDK) provides environment and tools for developing,
compiling, debugging, and executing a Java program.
JRE
Development Tools
Now, we'll focus on various development tools. Let's categorize these tools based on
their usage:
These tools lay the foundation of the JDK and are used to create and build Java
applications. Among these tools, we can find utilities for compiling, debugging,
archiving, generating Javadocs, etc.
They include:
javac – reads class and interface definitions and compiles them into class files
java – launches the Java application
javadoc – generates HTML pages of API documentation from Java source files
apt – finds and executes annotation processors based on the annotations present in
the set of specified source files
appletviewer – enables us to run Java applets without a web browser
jar – packages Java applets or applications into a single archive
jdb – a command-line debugging tool used to find and fix bugs in Java applications
javah – produces C header and source files from a Java class
javap – disassembles the class files and displays information about fields, constructors,
and methods present in a class file
extcheck – detects version conflicts between target Java Archive (JAR) file and
currently installed extension JAR files
These include key and certificate management tools that are used to manipulate
Java Keystores.
A Java Keystore is a container for authorization certificates or public key certificates.
Consequently, it is often used by Java-based applications for encryption, authentication,
and serving over HTTPS.
Also, they help to set the security policies on our system and create applications which
can work within the scope of these policies in the production environment. These
include:
For this purpose, the JDK brings native2ascii. This tool converts a file with
characters supported by JRE to files encoded in ASCII or Unicode escapes.
RMI enables an object running in one JVM to invoke methods on an object running in
another JVM. These tools include:
rmic – generates stub, skeleton, and tie classes for remote objects using the Java
Remote Method Protocol (JRMP) or Internet Inter-Orb Protocol (IIOP)
rmiregistry – creates and starts remote object registry
rmid – starts the activation system daemon. This allows objects to be registered and
activated in a Java Virtual Machine
serialver – returns serial version UID for specified classes
4.5. Java IDL and RMI-IIOP Tools
These tools enable distributed Java web applications to invoke operations on remote
network services using industry standard Object Management Group (OMG) – IDL.
RMI-IIOP, i.e. RMI over IIOP enables programming of CORBA servers and
applications via the RMI API. Thus enabling connection between two applications
written in any CORBA-compliant language via Internet InterORB Protocol (IIOP).
These tools help in deploying Java applications and applets on the web. They
include:
pack200 – transforms a JAR file into a pack200 file using the Java gzip compressor
unpack200 – transforms pack200 file into a JAR file
On the one hand, Java Plug-in establishes a connection between popular browsers and
the Java platform. As a result of this connection, applets on the website can run within a
browser.
On the other hand, htmlconverter is a utility for converting an HTML page containing
applets to a format for Java Plug-in.
JDK brings javaws. We can use it in conjunction with the Java Web Start.
This tool allows us to download and launch Java applications with a single click
from the browser. Hence, there is no need to run any installation process.
These are great tools that we can use to monitor JVM performance and resource
consumption. Here are a few of these: :
jconsole – provides a graphical console that lets you monitor and manage Java
applications
jps – lists the instrumented JVMs on the target system
jstat – monitors JVM statistics
jstatd – monitors creation and termination of instrumented JVMs
These are experimental tools that we can leverage for troubleshooting tasks: