Showing posts with label Java internal. Show all posts
Showing posts with label Java internal. Show all posts

Tuesday, June 7, 2022

JVM Run-Time Data Areas - Java Memory Allocation

The Java Virtual Machine (JVM) defines various run-time data areas that are used during the execution of the program. Some of these JVM data areas are created per thread where as others are created on JVM startup and memory area is shared among threads.

The JVM run-time data areas can be divided into six areas as per usage-

As stated above these memory areas can be categorized into two categories-

  • Created per thread– PC register, JVM stack, Native method stack
  • Shared by threads– Heap, Method area, Run-time constant pool
JVM run-time data areas

The Program Counter (PC) Register

In a JVM at any given time many threads may be executing. Each of the executing thread gets its own PC register.

If the method executed by the JVM thread is a JAVA method then the PC register contains the address of the Java Virtual Machine instruction currently being executed. In case, thread is executing a native method, the value of the Java Virtual Machine's pc register is undefined.

Java Virtual Machine (JVM) stacks

Each JVM thread has its own JVM stack which is created when the thread starts. JVM stack stores frames which are pushed and popped out of stack, a JVM stack is never manipulated directly.

At the time of any exception it is this stack trace you get where each element represents a single stack frame.

Exceptional conditions associated with Java Virtual Machine stacks:

  1. If the computation in a thread requires a larger Java Virtual Machine stack than is permitted, the Java Virtual Machine throws a StackOverflowError.
  2. If Java Virtual Machine stacks can be dynamically expanded, and expansion is attempted but insufficient memory can be made available to effect the expansion, or if insufficient memory can be made available to create the initial Java Virtual Machine stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

Frames in JVM Stacks

A new frame is created when a method is invoked, this frame is then pushed into the JVM stack for the thread. The frame is destroyed when the its method invocation completes.

Each frame has its own array of local variables, its own operand stack and a reference to the run-time constant pool of the class of the current method. The sizes of the local variable array and the operand stack are determined at compile-time and are supplied along with the code for the method associated with the frame.

At any point only one frame is active which is the frame for the executing method. This frame is referred to as the current frame, and its method is known as the current method. The class in which the current method is defined is the current class.

Note that a frame created by a thread is local to that thread and cannot be referenced by any other thread.

  • Local Variables- Each frame that is created and added to the JVM stack contains an array of variables known as its local variables.

    The length of the local variable array is determined at compile-time itself and supplied in the binary representation of a class or interface along with the code for the method associated with the frame.

    The JVM uses local variables to pass parameters when the method is invoked.

    If it is a class method, any parameters are passed in consecutive local variables starting from local variable 0.

    If it is an instance method, local variable 0 is always used to pass a reference to the object on which the instance method is being invoked i.e. this. Any parameters are subsequently passed in consecutive local variables starting from local variable 1.

  • Operand Stack– Each frame contains a Last In First Out (LIFO) stack called the operand stack of the frame. The maximum depth of the operand stack is known as the compile time itself and supplied along with the code for the method associated with the frame.

    Operand stack is the actual storage place at the time of method execution. When the frame is created for the method its operand stack is empty. The Java Virtual Machine will supply instructions to load constants or values from local variables or fields onto the operand stack. Other JVM instructions take operands from the operand stack, operate on them, and push the result back onto the operand stack.

    The operand stack is also used to prepare parameters to be passed to methods and to receive method results.

  • Performing Dynamic Linking- In the compiled .class file code for a method refers to methods to be invoked and variables to be accessed via symbolic references.These symbolic method references are translated into concrete method references through dynamic linking, loading classes as necessary to resolve symbols that are undefined at that point.

    Each frame in the JVM stack contains reference to the run-time constant pool for the type of the current method to support dynamic linking of the method code.

Native Method Stacks

A JVM may also use conventional stacks in order to support native methods. Native methods are the methods written in a language other than the Java programming language.

Native method stacks are allocated per thread when each thread is created.

The following exceptional conditions are associated with native method stacks:

  • If the computation in a thread requires a larger native method stack than is permitted, the Java Virtual Machine throws a StackOverflowError.
  • If native method stacks can be dynamically expanded and native method stack expansion is attempted but insufficient memory can be made available, or if insufficient memory can be made available to create the initial native method stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

Heap Area

Heap is the JVM run-time data area from which memory is allocated to objects, instance variables and arrays. Heap is created on the JVM start-up and shared among all Java Virtual Machine threads.

Once the object stored on the heap is not having any reference, memory for that object is reclaimed by garbage collector which is an automatic storage management system. Objects are never explicitly deallocated.

The following exceptional condition is associated with the heap:

  • If a computation requires more heap than can be made available by the automatic storage management system, the Java Virtual Machine throws an OutOfMemoryError.

Refer Heap Memory Allocation in Java to know more about Heap memory allocation and how garbage is collected here

Method area

JVM has a method area that is shared among all JVM threads. Method area stores meta data about the loaded classes and interfaces. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors.

Type information that is stored in method area for each type loaded by JVM is as follows–

  • Fully qualified name of the class/interface.
  • Fully qualified name of any direct superclass.
  • Modifier used.
  • Fully qualified names of any extended super interfaces.
  • Information to distinguish if loaded type is a class or interface.

Other than type information method area also stores–

  • Run time constant pool.
  • Field information which includes field name, type, modifier.
  • Method information which includes method name, modifier, return type, parameters.
  • Static (class) variables.
  • Method code which contains byte code, local variable size, operand stack size.

Method area is generally part of non-heap memory which used to be termed as PermGen space. Note here that PermGen Space is changed to MetaSpace from Java 8.

The following exceptional condition is associated with the method area:

  • If memory in the method area cannot be made available to satisfy an allocation request, the Java Virtual Machine throws an OutOfMemoryError.

Run-Time Constant Pool

A run time constant pool is a per class or per interface storage of the constant_pool table of the class. Constant_pool contains constants (string literals, numeric literals) which are known at compile-time, it also stores method and field references that must be resolved at run time.

Run-time constant pool is shared among the threads and allocated from the JVM’s method area.

Rather than storing everything in byte code a separate constant pool is maintained for the class and the byte code contains reference to the constant pool. These symbolic reference are translated into concrete method reference through dynamic linking.

As example – Here is a byte code snippet–

0: aload_0     
1: invokespecial #1       // Method java/lang/Object."<init>":()V      
4: aload_0       
5: new           #2       // class javafx/beans/property/SimpleStringProperty

If you notice here invokespecial operand has a prefix #1, this number (#1) is reference to the constant pool where instance initialization method is stored.

Same way in line 5 new Opcode is followed by number #2. Which means referring to the 2nd index in the constant pool.

The following exceptional condition is associated with the construction of the run-time constant pool for a class or interface:

  • When creating a class or interface, if the construction of the run-time constant pool requires more memory than can be made available in the method area of the Java Virtual Machine, the Java Virtual Machine throws an OutOfMemoryError.

Reference: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5

That's all for this topic JVM Run-Time Data Areas - Java Memory Allocation. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Just In Time Compiler (JIT) in Java
  2. Heap Memory Allocation in Java
  3. PermGen Space Removal in Java 8
  4. What are JVM, JRE and JDK in Java
  5. How to Run javap Programmatically From Java Program

You may also like-

  1. Reflection in Java - Getting Class Information
  2. Nested class and Inner class in Java
  3. Java Stream API Tutorial
  4. How HashMap Works Internally in Java
  5. Java Phaser With Examples
  6. Try-With-Resources in Java With Examples
  7. How to Create Immutable Class in Java
  8. How to Read Properties File in Spring Framework

Monday, May 16, 2022

Just In Time Compiler (JIT) in Java

In this post we'll see what is Just-In-Time (JIT) compiler in Java, how it works and how JIT compiler optimizes code.

When we start studying Java we get to know one of the prominent feature of Java is that Java is platform independent.

How is platform independence achieved in Java

In a short sentence, Java is platform independent because of the fact it is both compiled and interpreted.

To explain it further; first when we compile our JAVA code .class files are generated having the platform independent byte code which is interpreted to machine native code at run time by the JVM.

Where does JIT compiler fit

This two step process, though makes Java platform independent, where you are not worried about the OS or processor while writing your code, but at the same time execution is slow because byte code is interpreted to the native code at the run time. Because of this interpretation of the byte code to the host CPU's native instruction set there is an overhead of processor and memory usage which results in slow execution of the code.

That’s where Just-In-Time (JIT) compiler comes into the picture. In simple terms you can say JIT compiler compiles the already compiled code to the native code as per the processor. Since this compilation of the compiled byte code to the native machine code is done at the run time (Just in time) thus the name Just in Time compiler (JIT).

How does JIT compiler work in Java

While the code is executed JVM automatically monitors which methods are being executed frequently and start marking the methods that are “hot”. Note that JIT compiler initially itself doesn’t compile all the code at once, initially methods are interpreted from byte code.

Marked "hot" methods are scheduled for compilation into machine code. This compilation into machine code happens on a separate JVM thread without interrupting the execution of the program. While the hot method is compiled by the JIT compiler, the JVM will keep using the interpreted version of the method and switch over to the compiled method once it is ready.

Initial compilation of the method is quick but the resulting code may not be as efficient as it could be. If a method is used quite frequently the system can get a performance boost if the code for that particular method is regenerated in a more efficient way. That is why same method may get compiled more than once and more optimizations may get applied while the code is compiled.

Once the method is marked for compilation and compiled, its count is set to zero. If method call again reaches the call count threshold the method is recompiled and more optimizations are applied to the method to make it more efficient.

That recompilation and more optimization happens because the optimization techniques are often layered and once the compiler has applied one optimization then only it may be able to see other optimizations that can be applied.

JIT compiler in Java

How does JIT complier optimize code

Some of the optimization techniques used by JIT complier are-

  1. Inlining methods– One of the most common technique for optimizing code is method inlining. In method inlining the method call is substituted by the method body in the places where method is called. By replacing the method body in the method call the call to the method, resultant creation of stack frames is saved.

    Example code

    class A {
      B b;
      public void doProcessing() {
        x = b.getValue();
        ...
        ...
        y = b.getValue();
        ………………………….
    
      }
    }
    
    class B {
       int value;
       final int getValue() {
          return value;
       }
    }
    

    Inlining final method

    Notice in Class A method calls (getValue) are eliminated.

    class A {
      B b;
      public void doProcessing() {
        x = b.value;
        ...
        ...
        y = b.value;
        ………………………….
    
      }
    }
    

    Removing redundant loads

    y = b.value; is replaced with y = x so that local value itself can be used.
    class A {
      B b;
      public void doProcessing() {
        x = b.value;
        ...
        ...
        ...
        y = x;
        ………………………….
    
      }
    }
    
  2. Monomorphic dispatch– Java being an object-oriented language uses subtyping/polymorphism which means most of the method invocations are virtual method lookup. The JVM checks how many different implementations of the method are there –
    • If there is only one implementation it is a monomorphic dispatch.
    • If there are 2 then it is bimorphic dispatch, in case of more than 2 it is megamorphic dispatch.

    In the monomorphic case, path-dependent types (sub type or super type) does not happen. So, JIT compiler knows the exact method definitions that will be called when methods are called on the passed object, because there is no need to check which override is actually being used. This means JIT compiler can eliminate the overhead of doing virtual method lookup.

  3. Removing unwanted synchronization– Overhead of obtaining locks to enter a monitor can be eliminated by removing the synchronization, if synchronized block can only be accessed by a single thread.

    As example

    public void methodA{
      B b = new B()
      Synchronized(b){
       …..
       ……
      }
    }
    

    Here new object is created with in the method so every thread will have its own object thus the synchronized block has no effect here. JVM will notice that and the method will be optimized by JIT compiler.

  4. Merging adjacent synchronized block with same object – If there are adjacent synchronized block on the same object those will be merged as an optimization by the JIT compiler.
    Public void testMethod{
      synchronized(Test.class){
       ……
       …
      }
      synchronized(Test.class){
       ……
       …
      }
    }
    
    Here these 2 synchronized blocks can be merged to create a single synchronized block.

There are many other optimizations applied like loop optimization, dead code elimination.

Reference-

http://www.oracle.com/technetwork/articles/java/architect-evans-pt1-2266278.html
https://docs.oracle.com/cd/E15289_01/doc.40/e15058/underst_jit.htm

That's all for this topic Just In Time Compiler (JIT) in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Synchronization in Java - Synchronized Method And Block
  2. JVM Run-Time Data Areas - Java Memory Allocation
  3. Heap Memory Allocation in Java
  4. Garbage Collection in Java
  5. How to Compile Java Program at Runtime

You may also like-

  1. Executor And ExecutorService in Java With Examples
  2. Lock Striping in Java Concurrency
  3. Non-Blocking Algorithms
  4. Is String Thread Safe in Java
  5. Try-With-Resources in Java With Examples
  6. How HashMap Works Internally in Java
  7. Java Pass by Value or Pass by Reference
  8. BigInteger in Java With Examples

Sunday, January 30, 2022

Heap Memory Allocation in Java

In the post JVM run-time data areas we have already got a brief idea about the memory areas used while running a Java application. In this post we’ll talk about Java Heap memory space in detail – How Heap memory is allocated, how garbage collection happens, heap memory tuning and heap memory profiling.


Heap memory allocation in Java

Heap is the JVM run-time data area where the Java objects reside. Apart from Java objects, memory for instance variables and arrays is also allocated on the heap. Heap is created on the JVM start-up and shared among all Java Virtual Machine threads.

Heap memory in Java is divided into two areas (or generations)-

  • Young Space (generation)- The young generation consists of eden and two survivor spaces. Most objects are initially allocated in eden.
  • Old Space (or Tenured generation)– When objects (which have survived garbage collection) residing in young space have reached a certain age threshold they are moved to old space.

These generations have their own memory pool allocated by the JVM.

Java heap memory generations
Heap memory areas

Why is heap memory managed in generations

Here let’s deviate a little and try to understand why memory is managed in generations and what benefit do we get out of it. In one line it can be explained as these division into generations makes garbage collection more efficient.

As you must be knowing Garbage collection in Java is an automatic storage management system that frees space in the heap by reclaiming memory for objects that are not having any reference. Note that, an object is considered garbage when it can no longer be reached from any pointer in the running program.

A very simplistic garbage collection algorithms will iterate over every reachable object. Any objects left over are considered garbage. With this algorithm the time taken is proportional to the number of live objects in the whole heap.

In order to minimize the time it takes to do garbage collection the approach taken by JVM is known as "generational collection". This approach works on the weak weak generational hypothesis, which states that most objects survive for only a short period of time.

In order to optimize for this hypothesis, memory is managed in generations. Initially objects are allocated in the young generation (Eden space) and most objects die there.

When the young generation fills up, it results in a minor collection (Minor GC) in which only the young generation is collected, that way rather than iterating over the objects in the whole heap only a small portion of the Heap (Young generation) is inspected for dead objects. If the hypothesis stated above holds true then most of the objects will die there and reclaimed with in the younger generation.

Only a small portion of the objects will survive the garbage collection in younger generation and after a certain time lapse will move to tenured generation. Eventually, the tenured generation will fill up and must be garbage collected, that will result in a major collection (Major GC), in which the entire heap is collected.

How does garbage collection work on the heap

Now that you know that Heap is divided into generations and how this division helps garbage collector to run more efficiently as GC has to go through only a part of the heap space and within that less space iteration most of the objects (Remember most of the objects die young!) can be garbage collected.

Let’s see in more detail how garbage collection works across these generations and what happens when minor GC is triggered and what happens when major GC is triggered.

  • Within the young generation initially any new objects are allocated to the eden space. Both survivor spaces (S0 and S1) are initially empty.
  • A minor garbage collection is triggered when eden space is filled up. All the unreferenced objects are garbage collected and reference objects are moved to the first survivor space (S0). One survivor space is empty at any time.
  • When the minor garbage collection is triggered next time, all the unreferenced objects are garbage collected and reference objects are moved to the survivor space. Note that this time referenced objects are moved to the second survivor space (S1). There is one more step; objects from the previous minor GC on the first survivor space (S0) have their age incremented and get moved to S1. Note that one survivor space is empty at any time.
  • This process of clearing eden space, moving the referenced objects to one of the survivor spaces, incrementing the age for the surviving objects keeps on repeating with every minor GC. There is also a check for object’s age reaching a certain threshold. Objects that reach the threshold are moved from young generation to the old generation.
  • With every minor GC aged objects will be moved from young to old generation space.
  • When that movement of object fills up the tenured space that triggers a major GC in which the entire heap is collected. Major garbage collection lasts much longer than minor collections because a significantly larger number of objects are involved. Apart from garbage collecting the objects, major GC also compacts the space as it is defragmented from cleaning of the objects.

Refer Garbage Collection in Java to know more about garbage collection process and available garbage collectors in Java

VM Heap Size tuning options in Java

Heap memory in Java will have three things – live objects, dead objects and some portion of the memory which is still free. The JVM heap size determines the frequency of garbage collection and the time spent on collecting garbage.

If you set a large heap size frequency of garbage collection will be less but the time spent on collecting garbage will be more because of the large size (means having more objects to inspect). On the other hand if you do the opposite then time spent on collecting garbage will be less but frequency will increase as smaller heap will fill faster.

An acceptable heap size is application-specific and should be adjusted using the provided options after analyzing the actual time and frequency of garbage collections.

Java heap size options

  1. Task: Setting initial heap size

    Option: -Xms

    As example: -Xms40m

  2. Task: Setting maximum heap size

    Option: -Xms

    As example: -Xmx512m

    At initialization of the JVM, the entire space for the heap is reserved. The size of the space reserved can be specified with the -Xmx option. If the value provided with the -Xms parameter is smaller than the value provided with the -Xmx parameter, then all of the space that is reserved for the heap is not committed to the virtual machine. The different generationso of the heap (Young and tenured) can grow to that limit (provided with -Xmx) as and when needed.

    It is recommended that you set initial heap size (-Xms) equal to the maximum heap size (-Xmx) to minimize garbage collections.

  3. If you have not given same values for parameters -Xms and -Xmx then the virtual machine will grow or shrink the heap at each garbage collection to try to keep the proportion of free space to live objects within a specific range. The options to set this target ranges are-

  4. Task: To maintain minimum percentage heap free space

    Option: -XX:MinHeapFreeRatio=<minimum>

    As example: -XX:MinHeapFreeRatio=40

  5. Task: To maintain maximum percentage heap free space

    Option: -XX:MaxHeapFreeRatio=<maximum>

    As example: -XX:MaxHeapFreeRatio=70

    With the parameters as used in the example let's try to understand these options better. If the percent of free space in a generation falls below 40%, then the generation will be expanded to maintain 40% free space, up to the maximum allowed size of the generation. Similarly, if the free space exceeds 70%, then the generation will be contracted so that only 70% of the space is free, subject to the minimum size of the generation.

  6. After heap size setting parameters another option that affects GC performance is the proportion of the heap dedicated to the young generation. If you set the young generation to be bigger, minor collections will occur less often. But that would mean a smaller tenured generation, which will increase the frequency of major collections.

    Three options for tuning the young generation are-

  7. Task: Setting the Young generation heap size

    Option: -XX:NewSize

    It is recommended to set -XX:NewSize to be one-fourth the size of the heap size.

  8. Task: Set the maximum size of the Young Generation heap size.

    Option: -XX:MaxNewSize

  9. Task: Controlling the ratio between young and tenured generation

    Option: -XX:NewRatio

    As example if you set -XX:NewRatio=3 that would mean the ratio between the young and tenured generation is 1:3. The size of the eden + survivor spaces will be one-fourth of the total heap size.

  10. You can also tune the size of the survivor spaces, for that you can use the parameter SurvivorRatio.

  11. Task: Tune the size of the survivor spaces

    Option: -XX:SurvivorRatio

  12. As example if you set -XX:SurvivorRatio=6 that would mean the ratio between eden and a survivor space is 1:6. Which means each survivor space will be one-sixth the size of eden, thus one-eighth the size of the young generation.

Heap memory profiling

Though there are many tools available to profile the memory, I am mentioning one I have already used Java VisulalVM. It’s free and comes bundled with JDK itself. Another tool you will find in the same location is jconsole which is also a monitoring tool.

To launch you just need to go to bin directory of your installed JDK folder and launch jvisualvm from there.

On the left side pane it will show the running Java applications, just click on the one you want to inspect.

Here I am demonstrating its use with a very simple application where I have created a thread and in that thread I am creating 5000 objects of another class with some thread pause (by using sleep method) in between. For this program I changed the -Xms and -Xmx so that the heap is small.

First image shows the heap when the program is just started, that’s why you see a very little variance in the used heap.

Second image is a snapshot of the heap memory when garbage collection occurred that is why you can see a sudden dip in the used heap memory. If you see at 3:50 PM in the graph you will see a GC activity which has taken 1.3% of CPU time.

Third image also shows a GC activity. At 3:52 PM you can see a barely visible blue mark showing GC activity and a corresponding dip in the used heap memory.

So using VisualVM GUI tool you can monitor your application’s memory usage, also analyze process threads and get a thread dump. Also profile the performance of your application by analyzing CPU and memory usage.

That's all for this topic Heap Memory Allocation in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. PermGen Space Removal in Java 8
  2. Just In Time Compiler (JIT) in Java
  3. What Are JVM, JRE And JDK in Java
  4. How to Run a Shell Script From Java Program
  5. How to Pass Command Line Arguments in Eclipse

You may also like-

  1. Reflection in Java - Getting Field Information
  2. Java Object Cloning - clone() Method
  3. Java Stream API Examples
  4. Lambda Expressions in Java 8
  5. Lock Striping in Java Concurrency
  6. AtomicInteger in Java With Examples
  7. Java ReentrantReadWriteLock With Examples
  8. How HashMap Works Internally in Java

Wednesday, December 29, 2021

Garbage Collection in Java

In the post Heap Memory Allocation in Java I have already explained why heap is divided into generations and how it helps in garbage collection by adopting an approach known as “generational collection”.

In this post we’ll see more details about garbage collection in Java, basic process of garbage collection, garbage collection tuning and types of garbage collectors available in Java.

What is Garbage Collection

Garbage collection in Java is an automatic process of inspecting the heap memory and identifying which objects are in use and which are not and deleting the unused objects after identification.

Here object which is in use (referenced object) means that a part of your program is still holding a reference to the object. Unused object (unreferenced object) means not referenced by any part of your program and can be deleted safely.

Basic Garbage Collection Process

Basic garbage collection process in Java has three steps-

  1. Marking
  2. Sweeping
  3. Compacting

Marking

The first step in the garbage collection process is called marking. In this step GC iterates through the memory and identifies which objects are still in use and which objects are unused.

Sweeping

In this step of sweeping (normal deletion) objects which are already marked as unused in the “marking” step are removed in order to free space.

Compacting

Deleting the unused objects fragments the memory which results in further memory allocation which are not contiguous. That is why there is another step which moves the reference objects together which results in having a contiguous free space thus making the new memory allocation much easier and faster.

garbage collection compacting process
garbage collection in Java

Performance parameters for GC

There are two goals for any application with respect to garbage collection–

  • Maximum pause time goal
  • Application throughput goal

Maximum Pause Time Goal

All minor garbage collections and major garbage collections are "Stop the World" events which means all application threads are stopped until the garbage collection completes. So, the goal here is to minimize this pause time or restrict it by putting an upper limit.

That is what this parameter does; maximum pause time goal is to limit the longest of these pauses.

Note here that only parallel collector provides a command line option to specify a maximum pause time goal.

Command line option

-XX:MaxGCPauseMillis=<nnn> 

This option is a hint to the garbage collector that pause times of <nnn> milliseconds or less are desired.

Throughput Goal

Since garbage collection is "Stop the world event" stopping all the application threads so we can divide the total time into-

  • The time spent collecting garbage
  • The application time

The throughput goal is measured in terms of the time spent collecting garbage and the time spent outside of garbage collection.

Note here that only parallel collector provides a command line option to specify a throughput goal.

Command line option

-XX:GCTimeRatio=<nnn>

The ratio of garbage collection time to application time is 1 / (1 + <nnn>). For example, -XX:GCTimeRatio=9 sets a goal of 1/10th or 10% of the total time for garbage collection.

Garbage collectors available in Java

The Java HotSpot VM has three different types of collectors-

  1. Serial GC
  2. Parallel GC also known as Throughput Collector.
  3. Mostly Concurrent Collector – Java HotSpot offers two types of mostly concurrent collector.
    • Concurrent Mark Sweep (CMS) Collector
    • Garbage First, Garbage collector (G1 Collector)

Serial Collector

The serial collector uses a single thread to do both minor and major collections. The serial collector is best-suited to single processor machines, because it cannot take advantage of multiprocessor hardware. Since only a single thread performs garbage collection so Serial GC is most suited for applications that do not have low pause time requirements.

Command Line Switches

The serial collector is selected by default on certain hardware (client machines) and operating system configurations. Serial collector can be explicitly enabled with the option

-XX:+UseSerialGC.

Parallel Collector

In parallel collector (also known as the throughput collector) multiple threads are used for garbage collection.

The command line option to enable parallel collector is -XX:+UseParallelGC.

By default, with this option, both minor and major collections are executed in parallel to further reduce garbage collection overhead.

The feature that enables the parallel collector to perform major collections in parallel is known as parallel compaction. If parallel compaction is not enabled then major collections are performed using a single thread.

Command line option to turn off parallel compaction is : -XX:+UseParallelOldGC.

Only parallel collector provides command line options to tune the performance parameters as stated above.

Command Line Switches

  • Maximum Garbage Collection Pause Time: The maximum pause time goal is specified with the command-line option -XX:MaxGCPauseMillis=<N>.
  • Throughput goal: The throughput goal is specified by the command-line option -XX:GCTimeRatio=<N>

Concurrent Mark Sweep (CMS) Collector

Concurrent Mark Sweep (CMS) Collector, as the name suggests, performs garbage collection concurrently while the application is running. Since application also keep running that results in low pause time but the application throughput is affected because processor resources are shared.

This collector should be considered for any application with a low pause time requirement.

Like other available collectors the CMS collector is generational; thus both minor and major collections occur. The CMS collector attempts to reduce pause times due to major collections by using separate garbage collector threads to trace the reachable objects concurrently with the execution of the application threads. CMS (Concurrent Mark Sweep) garbage collection does not do compaction.

Pauses in CMS collector

The CMS collector pauses an application twice during a concurrent collection cycle. The first pause marks those objects as live which are directly reachable from the roots and from elsewhere in the heap. This first pause is referred to as the initial mark pause.

The second pause comes at the end of the concurrent tracing phase and finds objects that were missed by the concurrent tracing due to updates by the application threads of references in an object after the CMS collector had finished tracing that object. This second pause is referred to as the remark pause.

Command Line Switches

  • The command line option to enable CMS collector is -XX:+UseConcMarkSweepGC.
  • Command line option to set the number of threads -XX:ParallelCMSThreads=<n>

Garbage-First Garbage Collector

The Garbage-First (G1) garbage collector is a server-style garbage collector which is suited for multiprocessor machines with large memories. G1 garbage collector minimizes the garbage collection (GC) pause time while achieving high throughput at the same time.

It minimizes the garbage collection (GC) pause time by trying to adhere to pause time goals which is set using the flag MaxGCPauseMillis.

Technique used by G1 collector

Technique used by G1 collector to achieve high performance and pause time goals is explained below-

G1 Collector partitions the heap into a set of equally sized heap regions.

Image credit- https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html

Initially G1 performs a concurrent global marking throughout the heap to determine which objects are still referenced and which are not (unreferenced). Once the marking is done G1 knows which regions are mostly empty. It collects these mostly empty regions first thus the name Garbage-First. By using this method of garbage collection G1 frees the large amount of free space by sweeping only a small region of heap.

G1 tries to adhere to the specified pause time target (defined by using flag MaxGCPauseMillis) by using a pause prediction model. It calculates how many regions can be collected within the given pause time limit and collects only those regions.

G1 is generational in a logical sense

As already stated heap is partitioned into a set of equally sized heap regions. A set of empty regions is designated as the logical young generation. Objects are allocated from that logical young generation and that young generation (those regions of heap) is garbage collected when it is full. In some cases, regions outside the set of young regions (regions designated as tenured generation) can be garbage collected at the same time. This is referred to as a mixed collection.

G1 collector also compacts the memory by copying the live objects to selected, initially empty regions.

G1 collector changes in Java Versions

G1 collector is the default garbage collector Java 9 onward. Till Java 8 default garbage collector was Parallel GC.

Though G1 garbage collector is designed to avoid full collections but a full GC occurs if memory is not reclaimed fast enough with in the pause time target. In Java 9 implementation of the full GC for G1 used a single threaded mark-sweep-compact algorithm which meant an increased pause time.

Java 10 onward G1 collector uses the parallelized mark-sweep-compact algorithm to minimize the impact for users experiencing full GCs.

Command Line Switches

The command line option to enable G1 collector is -XX:+UseG1GC.

Reference-

http://www.oracle.com/technetwork/articles/java/architect-evans-pt1-2266278.html
https://docs.oracle.com/cd/E15289_01/doc.40/e15058/underst_jit.htm

That's all for this topic Garbage Collection in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Just In Time Compiler (JIT) in Java
  2. JVM Run-Time Data Areas - Java Memory Allocation
  3. Heap Memory Allocation in Java
  4. PermGen Space Removal in Java 8
  5. How to run javap programmatically from Java Program

You may also like-

  1. What are JVM, JRE and JDK in Java
  2. Java Reflection API Tutorial
  3. Transient Keyword in Java With Examples
  4. Java Stream API Examples
  5. Busy Spinning in Multi-Threading
  6. How HashMap Works Internally in Java
  7. Callable and Future in Java With Examples
  8. Core Java Basics Interview Questions And Answers

Wednesday, August 4, 2021

Running Dos/Windows Commands From Java Program

If you want to run DOS or Windows commands from a Java program it can be done using RunTime class or ProcessBuilder (Note ProcessBuilder is added in Java 5).

Java RunTime class

Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime method.

In RunTime class there is a exec() method that executes the specified string command in a separate process. Using this exec() method dos or windows commands can be executed from Java.

Runtime.getRunTime().exec to run dos/windows commands in Java example

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class RunningCommand {
  public static void main(String[] args) {
    Process p;
    try {
      p = Runtime.getRuntime().exec("cmd /c dir");

      p.waitFor(); 
      BufferedReader reader=new BufferedReader(new InputStreamReader(
                  p.getInputStream())); 
      String line; 
      while((line = reader.readLine()) != null) { 
        System.out.println(line);
      } 
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

Output

Volume in drive C is OS
Volume Serial Number is AEC2-FEE9

 Directory of C:\workspace\abc

10/19/2016  12:39 PM    <DIR>          .
10/19/2016  12:39 PM    <DIR>          ..
10/24/2016  03:22 PM               592 .classpath
10/19/2016  12:39 PM               379 .project
10/19/2016  12:39 PM    <DIR>          .settings
10/21/2016  03:16 PM    <DIR>          bin
10/19/2016  12:39 PM    <DIR>          src
               2 File(s)            971 bytes
               5 Dir(s)  40,032,706,560 bytes free

Here it can be seen that directory listing is displayed for the directory which happens to be the workspace directory from where I executed the Java program.

Runtime.getRuntime().exec method is used to run the command.

  • public static Runtime getRuntime() - Returns the runtime object associated with the current Java application.
  • public Process exec(String command) throws IOException - Executes the specified string command in a separate process.

cmd /c which is used with the command has the following explanantion -

  • cmd- Starts a new command shell
  • /c- Executes the given command and terminates

Execution of the command returns instance of class Process. Using the getInputStream() method of Process class output of the executed command can be printed by reading the stream.

Running command Using ProcessBuilder

You can also use ProcessBuilder class to run dos or windows command from Java. If you have to run the same command as used above using ProcessBuilder, which is a much clearer way to do that, you can create a list with the command and the required arguments and then pass it to ProcessBuilder instance as command.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class RunningCommand {
  public static void main(String[] args) {
    Process p;
    try {
      List<String> cmdList = new ArrayList<String>();
      cmdList.add("cmd");
      cmdList.add("/c");
      cmdList.add("dir");
      ProcessBuilder pb = new ProcessBuilder();
      pb.command(cmdList);
      p = pb.start();
    
      p.waitFor(); 
      BufferedReader reader=new BufferedReader(new InputStreamReader(
                p.getInputStream())); 
      String line; 
      while((line = reader.readLine()) != null) { 
        System.out.println(line);
      } 
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

That's all for this topic Running Dos/Windows Commands From Java Program. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. How to Compile Java Program at Runtime
  2. How to Run javap Programmatically From Java Program
  3. How to Run a Shell Script From Java Program
  4. How to Run Threads in Sequence in Java
  5. Print Odd-Even Numbers Using Threads And wait-notify Java Program

You may also like -

  1. Difference Between Two Dates in Java
  2. Initializer block in Java
  3. How to Remove Duplicate Elements From an ArrayList in Java
  4. TreeMap in Java With Examples
  5. Java Exchanger With Examples
  6. ConcurrentSkipListMap in Java With Examples
  7. Inter-thread Communication Using wait(), notify() And notifyAll() in Java
  8. Functional Interfaces in Java

Wednesday, June 9, 2021

How to Run javap Programmatically From Java Program

This post is about running javap command programmatically from a Java program. In Java it can be done using ProcessBuilder class which is used to create operating system processes.

When do we need javap command

If you have a .class file or a jar with .class files and you want to see the structure of a .class file javap is a good option to do that.

The javap command disassembles one or more class files. It comes with JDK under tools.jar and used to get the mnemonical representation of the .class file.

ProcessBuilder class

ProcessBuilder has a constructor that takes the command as a list

  • ProcessBuilder(List<String> command) - Constructs a process builder with the specified operating system program and arguments.

You can use this constructor to construct a process with javap command, -c argument and path of the class file. Also make sure that you have tools.jar (which comes with JDK) in your classpath.

Java Program to run javap

Suppose you have a class called First.java

public class First {

 public static void main(String[] args) {
  First first = new First();
  first.showDetails();
 }
 
 public void showDetails(){
  System.out.println("In Show details" );
 }
}

You want to run javap command for the compiled .class file of First.java.

So, the command you want to run is :
javap –c First.class. Let’s see how you can run this command from a Java program to disassemble a .class file at run time.

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class ClassStructure {

 public static void main(String[] args) {
  try {
   List<String> cmdList = new ArrayList<String>();
   cmdList.add("C:\\Program Files\\Java\\jdk1.8.0_111\\bin\\javap.exe");
   cmdList.add("-c");
   cmdList.add("D:\\First.class");
   
   // Constructing ProcessBuilder with List as argument
   ProcessBuilder pb = new ProcessBuilder(cmdList);
   
   Process p = pb.start();
   p.waitFor();
   InputStream fis = p.getInputStream();
   
   DisplayClassStructure(fis);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
  }
 }
 
 // Method used for displaying the disassembled class
 private static void DisplayClassStructure(InputStream is){
  
  InputStream stream;
  
  try {
   
   BufferedReader reader = new BufferedReader(new InputStreamReader(is));
   String line;   
   while ((line = reader.readLine()) != null) {   
        System.out.println(line);   
   }
   // Better put it in finally
   reader.close();
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

Output

Compiled from "First.java"
public class org.test.First {
  public org.test.First();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #1                  // class org/test/First
       3: dup
       4: invokespecial #16                 // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #17                 // Method showDetails:()V
      12: return

  public void showDetails();
    Code:
       0: getstatic     #23                 // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #29                 // String In Show details
       5: invokevirtual #31                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

That's all for this topic How to Run javap Programmatically From Java Program. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. How to Compile Java Program at Runtime
  2. Running Dos/Windows Commands From Java Program
  3. How to Create Deadlock in Java
  4. Unzip File in Java
  5. Print Odd-Even Numbers Using Threads And wait-notify Java Program

You may also like-

  1. How to Find Last Modified Date of a File in Java
  2. How to create PDF from XML using Apache FOP
  3. StringBuffer Class in Java With Examples
  4. Constructor Chaining in Java
  5. How to Fix The Target Type of This Expression Must be a Functional Interface Error
  6. forEach Statement in Java 8
  7. Varargs (Variable-length Arguments) in Java
  8. Executor And ExecutorService in Java With Examples

Tuesday, June 8, 2021

PermGen Space Removal in Java 8

Though Java 8 introduced many new features to the Java language which are tangible in a way that you can see and use them like lambda expressions and stream API. But there are other changes too which you won’t use in your day to day work but are equally important. One of these changes is to remove PermGen space in Java and replacing it with Metaspace.

Knowledge about the memory management in Java will definitely help you in improving the performance of your application so in this post we’ll see what is PermGen space, why it is replaced with Metaspace and what options are there when using Metaspace in Java.

What is PermGen space in Java

Let’s have a brief introduction of PermGen space first in order to understand this post better.

PermGen (Permanent generation) space stores the meta-data about the class. That involves information about the class hierarchy, information about the class like its name, fields, methods, bytecode. Run time constant pool that stores immutable fields that are pooled in order to save space like String are also kept in PermGen.

Problem with PermGen space

PermGen space is contiguous to heap space and the information stored in PermGen is relatively permanent in nature (not garbage collected as swiftly as in young generation like Eden).

The space allocated to PermGen is controlled by the argument -XX:MaxPermSize and the default is 64M (30% higher in 64 bit JVM which means around 83M in a 64 bit JVM).

Here point to note is PermGen's size is Fixed at start-up and can't be changed dynamically which may lead to java.lang.OutOfMemoryError: PermGen error. As your application grows the classes that are loaded will grow and the size of class metadata may become more than what was the size of the PermGen space. Once the permanent generation space is full OutOfMemoryError: PermGen Space error occurs.

Introducing MetaSpace in Java

In Java 8 PermGen space has been completely removed so using argument -XX:MaxPermSize won’t do anything.

For example, if I go to eclipse where compiler compliance level is Java 1.8 and set a VM argument for MaxPermSize, it will give me warning for this option.

permgen space in Java
“Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0”

In place of PermGen a new space MetaSpace has been introduced. How it differs from PermGen is that it is not contiguous to Heap space, it is part of native memory instead. You can also opt to use default value for MetaSpace (Though there are some flags provided to limit the memory usage) which theoretically means total available native memory.

Options with Metaspace

There are some new flags added for Metaspace in JDK 8 two of them are analogous to the option provided with PermGen; PermSize and MaxPermSize. In Metaspace options are MetaspaceSize and MaxMetaspaceSize. Other two flags are MinMetaspaceFreeRatio and MaxMetaspaceFreeRatio.

Before going into those options just a brief introduction about the class metadata and how it is garbage collected.

Metadata of the class is deallocated when the corresponding Java class is unloaded. Garbage collections may be induced in order to unload classes and deallocate class metadata. Garbage collection is induced when the space committed for class metadata reaches a certain level (a high-water mark). This level (a high-water mark) in metaspace is defined by MetaspaceSize (Default - 12Mbytes on the 32bit client VM and 16Mbytes on the 32bit server VM with larger sizes on the 64bit VMs). After the garbage collection, the high-water mark may be raised or lowered depending on the amount of space freed from class metadata.

-XX:MetaspaceSize=<M> Where <M> is the initial amount of space(the initial high-water-mark) allocated for class metadata (in bytes) that may induce a garbage collection to unload classes. It is raised or lowered based on the options MaxMetaspaceFreeRatio and MinMetaspaceFreeRatio. If the committed space available for class metadata as a percentage of the total committed space for class metadata is greater than MaxMetaspaceFreeRatio, then the high-water mark will be lowered. If it is less than MinMetaspaceFreeRatio, then the high-water mark will be raised.

-XX:MaxMetaspaceSize=<M> Where <M> is the maximum amount of space to be allocated for class metadata (in bytes). The amount of native memory that can be used for class metadata is by default unlimited. Use the option MaxMetaspaceSize to put an upper limit on the amount of native memory used for class metadata.

-XX:MinMetaspaceFreeRatio=<M> Where <M> is the figure in percentage (minimum percentage of class metadata capacity free after a GC). It is used in conjunction with the MetaspaceSize option to determine whether high-water mark should be raised so as not to induce another garbage collection too soon.

-XX:MaxMetaspaceFreeRatio=<M> Where <M> is the figure in percentage (maximum percentage of class metadata capacity free after a GC). It is used in conjunction with the MetaspaceSize option to determine whether high-water mark should be reduced.

Using default option

You may be tempted to use the default with the Metaspace so that more and more space is allocated for the class meta-data but in my opinion that may result in false sense of security that every thing is fine with your application where as in reality your application may have memory leak issues.

You should provide enough space for the Metaspace so that classes of your application and any third party libraries are loaded then you should monitor it for any memory leaks in case that space is not enough. There are instances when I had to increase PermGen space when application itself was big and using third party tools like reporting engines. But that was a genuine case where it had to be increased up to certain level. If it still gave “ OutOfMemoryError” that meant memory leaks which had to be addressed rather than increasing PermGen space even more.

That's all for this topic PermGen Space Removal in Java 8. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Just In Time Compiler (JIT) in Java
  2. Heap Memory Allocation in Java
  3. Method Reference in Java
  4. Optional Class in Java With Examples
  5. Effectively Final in Java 8

You may also like-

  1. Spliterator in Java
  2. Interface Default Methods in Java
  3. forEach statement in Java 8
  4. Non-Blocking Algorithms in Java
  5. Busy Spinning in Multi-Threading
  6. Callable and Future in Java With Examples
  7. Java ReentrantLock With Examples
  8. Try-With-Resources in Java With Examples

Saturday, March 20, 2021

How to Run a Shell Script From Java Program

This post talks about how you can execute a shell script from a Java program.

If you have a shell script say test.sh then you can run it from a Java program using RunTime class or ProcessBuilder (Note ProcessBuilder is added in Java 5).

Shell script

echo 'starting script'
mkdir test
cd test
touch SAMPLE

Using Runtime.getRunTime().exec to execute shell script

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class RunningSS {
 public static void main(String[] args) {
  Process p;
  try {
   String[] cmd = { "sh", "/home/adb/Documents/test.sh"};
   p = Runtime.getRuntime().exec(cmd); 
   p.waitFor(); 
   BufferedReader reader=new BufferedReader(new InputStreamReader(
    p.getInputStream())); 
   String line; 
   while((line = reader.readLine()) != null) { 
    System.out.println(line);
   } 
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

After executing this Java program with the given shell script, if you verify at the location where your Java program is you will see a directory test created and a file SAMPLE with in that directory.

Monday, March 15, 2021

How to Compile Java Program at Runtime

This post talks about how you can compile a java program at runtime. You may have a case where you get a Java file path by reading a property file and you need to compile and run that Java file or you may have a scenario where at run time a program file is created rather than some script which you need to compile and run.

In such cases you need to compile your code at run time from another Java program. It can be done using JavaCompiler interface and ToolProvider class. Note that these classes are provided from Java 6.

Also note that you will need JDK to run it not JRE, so you need to have JDK libraries not JRE. If you are using eclipse and your JRE System library is pointing to JRE path make sure it points to JDK. You can do that by right clicking on your project and going to Java Build Path through properties. There click on Libraries tab and select the JRE System Library which points to jre path and click Edit.