Core Java Interview Questions Core Java Interview Questions

Page content

Comprehensive List of Java Interview Questions based on my personal interview experience over the last few years. Sequence of Questions in each section are in the order of recent interview trends. Keep following this post link for regular updates.

Also Read Java 8 Interview Questions
Also Read Java Multithreading (Concurrency) Interview Questions

Java Design Patterns

Q1. What is Singleton Pattern and how do you implement it?

Singleton design pattern ensures that a class has only one instance and provides a global point of access to it.

This is one of the most commonly asked question in interviews. Then interviewer asks to implement a Singleton Design Pattern Using Java.

Follow up questions in singleton pattern are as follows:

  • How to make singleton class thread safe?
    using double checked locking
  • How to prevent deserialization to create new object of singleton class?
    using readResolve method to return same instance
  • How to prevent cloning to create a new object of singleton class?
    override clone method to return same instance
  • How to prevent reflexion to create a new object of singleton class?
    throw exception from private constructor if instance already exist
Singleton Class
public class Singleton implements Serializable, Cloneable{

 private static final long serialVersionUID = 1L;

 private static Singleton instance = null;
 
 private static Object DUMMY_OBJECT = new Object();
 
 private Singleton(){
  /*To prevent object creation using reflection*/
  if(instance!=null){
   throw new InstantiationError( "Singleton Object is already created." );
  }
 }
 
 public static Singleton getInstance(){
  /*Double checked locking*/
  if(instance == null){
   synchronized (DUMMY_OBJECT) {
    if(instance == null){
     instance = new Singleton();
    }
   }
  }
  return instance;
 }
 
 public static void print(){
  System.out.println("I am a singleton class.");
 }
 
 /*To prevent object creation using deserialization*/
 private Object readResolve() throws ObjectStreamException{
  return instance;
 }
 
 /*To prevent object creation using cloning*/
 @Override
 protected Object clone() throws CloneNotSupportedException {
  return instance;
 }
}

Q2. What is Immutable Object? How do you write an Immutable Class?

Immutable Class means that once an object is initialized from this Class, we cannot change the state of that object.

In other words, An immutable object can’t be modified after it has been created. When a new value is needed, the accepted practice is to make a copy of the object that has the new value.

In order to create an Immutable Class in Java, you should keep following points in mind:-

  1. Declare the class as final so that it cannot be extended and subclasses will not be able to override methods.
  2. Make all the fields as private so direct access in not allowed
  3. Make all the fields as final so that value cannot be modified once initialized
  4. Provide no setter methods — setter methods are those methods which modify fields or objects referred to by fields.
  5. Initialize all the final fields through a constructor and perform a deep copy for mutable objects.
  6. If the class holds a mutable object:
    • Don’t provide any methods that modify the mutable objects.
    • Always return a copy of mutable object from getter method and never return the actual object reference.

Let’s apply all the above points and create our immutable class ImmutablePerson

ImmutablePerson.java
/**
 * Immutable class should mark as final so it can not be extended. 
 * Fields should mark as private so direct access is not allowed.
 * Fields should mark as final so value can not be modified once initialized.
 **/
public final class ImmutablePerson {

    // String - immutable
    private final String name;
    
    // Integer - immutable
    private final Integer weight;
    
    // Date - mutable
    private final Date dateOfBirth;
    
    /**
     * All the final fields are initialized through constructor
     * Perform a deep copy of immutable objects
     */
    public ImmutablePerson(String name, Integer weight, Date dateOfBirth){
        this.name = name;
        this.weight = weight;
        this.dateOfBirth = new Date(dateOfBirth.getTime());
    }
    
    /**********************************************
     ***********PROVIDE NO SETTER METHODS *********
     **********************************************/
    
    /**
     * String class is immutable so we can return the instance variable as it is
     **/
    public String getName() {
        return name;
    }
    
    /**
     * Integer class is immutable so we can return the instance variable as it is
     **/
    public Integer getWeight() {
        return weight;
    }
    
    /**
     * Date class is mutable so we need a little care here.
     * We should not return the reference of original instance variable.
     * Instead a new Date object, with content copied to it, should be returned.
     **/
    public Date getDateOfBirth() {
        return new Date(dateOfBirth.getTime());
    }
    
    @Override
    public String toString() {
    	return "Person { name: " + name + ", weight: " + weight + ", dateOfBirth: " + new SimpleDateFormat("dd-MM-yyyy").format(dateOfBirth) + "}";
    }
}

Q3. Give example of 5-6 design patterns being used in Java classes.

  • Factory
    java.util.Calendar#getInstance()
  • Static Factory
    Long#valueOf()
  • Abstract Factory
    javax.xml.parsers.DocumentBuilderFactory#newInstance()
    javax.xml.transform.TransformerFactory#newInstance()
    javax.xml.xpath.XPathFactory#newInstance()
    java.util.Collections#emptyMap()
    java.util.Collections#emptyList()
    java.util.Collections#emptySet()
  • Builder
    java.lang.StringBuilder#append()
    java.lang.StringBuffer#append()
  • Decorator
    All subclasses of java.io.InputStream, OutputStream, Reader and Writer.
  • Chain of responsibility
    javax.servlet.Filter#doFilter()
  • Iterator
    java.util.Iterator
  • Observer
    JMS message listener
  • Singleton
    java.lang.Runtime#getRuntime()
  • Adapter
    java.util.Arrays#asList()
    java.io.InputStreamReader(InputStream) (returns a Reader)
    java.io.OutputStreamWriter(OutputStream) (returns a Writer)
  • Immutable
    String, Integer, Byte, Long, Float, Double, Character, Boolean and Short

Q4. Anti patterns in Java. What is god class?

Anti patterns in java is:-

  • Any pattern or coding habit which is considered as bad practice
  • Which are against SOLID design principles

God class is one of the Anti pattern example. A god class is a class which is having too many properties or methods or dependencies and hence lots of responsibilities which violates single-responsibility SOLID design principle. Writing thousands lines of code in single class becomes a nightmare to debug, unit-test and document.

Java DataStructure

Q1. How HashMap Works?

This is also most commonly asked question in collections. Interviewer start this question asking about collections and what are the data structure/collection you have used in development. Candidate generally answers HashMap, LinkedList, ArrayList, HashSet. Then interviewer check your knowledge of equals, hashcode and hashing algorithm. You should be aware of HashMap class internal implementation.

Read Design your own HashMap in Java for HashMap implementation. Follow up questions in HashMap are as follows:

  • How to use HashMap in multi threading environment?
    You should know that HashTable is thread safe. You can make HashMap thread safe by using Collections.synchronizedMap(Map)
  • What is Concurrent HashMap? How it is better then thread safe HashMap in multi threading environment?
    Synchronized HashMap locks the whole map when one thread is accessing it resulting into other thread to wait. Concurrent HashMap provides the better performance by locking only the specific segment (similar to bucket in hashmap) rather than blocking whole map. By default, there are 16 segments, means 16 locks, means 16 concurrency level, means 16 threads can access 16 different segment of the map at the same time.

Q2. What is the difference in ArrayList and LinkedList?

ArrayList vs LinkedList
ArrayList LinkedList
1. ArrayList implements List and RandomAccess interfaces LinkedList implements List and Deque interface
2. ArrayList internally uses a dynamic array to store the elements. LinkedList internally uses a doubly linked list to store the elements.
3. ArrayList elements are stored in contiguous memory location where each memory location represents an index Each LinkedList element can be stored at different memory location where each element has address of it previous and next element.
4. Insertion and Deletion of elements is slow in ArrayList as these operations require all the elements to shift by one index to either make the space or fill the empty space Insertion and Deletion of elements is faster in LinkedList as these operations just require to change the addresses in previous and next block
5. Read operation of random element is much faster in ArrayList due to indices and support of fast random access Read operation of random element is slower in LinkedList as need to traverse the list of find element
6. Recommended when read operation is more than the number of insertions and deletions Recommended when insertion and deletion rate is higher then the read operation
methods ArrayList LinkedList
get(int index) O(1) O(n) with n/4 steps on average
getFirst(), getLast() NA O(1)
add(int index, E element) O(n) with n/2 steps on average O(n) with n/4 steps on average
addFirst(), addLast() NA O(1)
remove(int index) O(n) with n/2 steps on average O(n) with n/4 steps on average
removeFirst(), removeLast() NA O(1)
Iterator.remove() O(n) with n/2 steps on average O(1)
ListIterator.add(E element) O(n) with n/2 steps on average O(1)
  • ArrayList: Many of the operations need n/2 steps on average, constant number of steps in the best case (end of list), n steps in the worst case (start of list)
  • LinkedList: Many of the operations need n/4 steps on average, constant number of steps in the best case (e.g. index = 0), and n/2 steps in worst case (middle of list)

Q3. How to find middle element of Linked List?

  • It is always better to keep track of Linked list size by increasing or decreasing the counter by 1, on addition or deletion of nodes from linked list respectively. In this way, middle element’s index will be (size -1)/2
  • When size of the linked list is unknown and only head node is given then you should use Fast and Slow pointer approach.
    In this approach, we iterate through the linked list using two pointers. Fast pointer jumps 2 nodes in each iteration, and the slow pointer jumps only one node per iteration.
    When the fast pointer reaches the end of the list, the slow pointer will be at the middle element.

Also read How to find middle element of LinkedList in Java for more details


Q4. How to find a loop in LinkedList?

If you answer it then follow up question might be asked:

  • How to find the starting point of loop in LinkedList?
  • How to find the length of the loop in LinkedList?

Q5. Difference between ArrayList and Vector.

These is legacy interview questions which is not asked frequently now a days but good to know.

ArrayList vs Vector
ArrayList Vector
1. ArrayList’s methods are not synchronized Vector’s methods are synchronized
2. ArrayList is fast as it’s non-synchronized. Vector is slow because it is synchronized
3. If internal array runs out of room, ArrayList increases its size by 50% Vector defaults to doubling size of its array
4. ArrayList can only use Iterator for traversing Vector can use both Enumeration and Iterator for traversing over elements

Java String

Q1. What is String Constant Pool?

String Constant Pool is a pool of Strings (String literals) stored in Java Heap Memory. A dedicated space is provided for pool in Heap Memory.

When you ask for a string from this pool, it provides the same string if already exist, otherwise it creates a new string in the pool and returns that string. This process is also called as string intern which makes the string literals reusable.

Q2. Difference between String Literal and New String Object.

String literal vs New String Object
String Literals New String Object
String literals are maintained in String Constant Pool New String objects are created in Heap Memory
String literals are interned by default New String objects can be interned explicitly using intern() method
  // String Literal
  String a = "abc"; 
  String b = "abc";
  System.out.println(a == b);  // true

  // String Object
  String c = new String("abc");
  String d = new String("abc");
  System.out.println(c == d);  // false
  System.out.println(a == d);  // false
  System.out.println(a == d.intern());  // true
  System.out.println(c.intern() == d.intern());  //true

Q3. Difference between String, StringBuilder and StringBuffer.

String vs StringBuilder vs StringBuffer
  • String object is immutable whereas StringBuffer and StringBuilder objects are mutable.
  • String’s concat “+” operator internally uses StringBuffer or StringBuilder class.
StringBuilder vs StringBuffer
  • StringBuilder and StringBuffer provides similar methods such as substring(), insert(), append(), delete()
  • StringBuffer is thread safe and synchronized whereas StringBuilder is not, thats why StringBuilder is more faster than StringBuffer.
  • Most of the time you will be using StringBuilder. Use StringBuffer if you really are trying to share a buffer between threads.

Q4. Why char[] array is used over String to store password in Java?

Strings are immutable in Java and any change in a String object produces a new String. When you store passwords in a String object, they stays in memory until Garbage collector clear it, which is a security threat as anyone with access to the memory dump retrieve the password from memory.

Moreover, String use String Pool memory for reusability, which even stays in memory for long duration as compare to other objects.

Whereas if password is stored in char[] array, we can explicitly wipe the password after completing the work. The array can be overwritten and password will no longer be there in memory.

Java OOPS

Java OOPS concepts are very frequently asked interview questions for Java beginners.

Q1. What is Polymorphism in Java?

Polymorphism means “many forms”, and it allows us to perform same action on an object in different ways.

There are two types of polymorphism in java:

  1. Static Polymorphism also known as compile time polymorphism - example is Method Overloading
  2. Dynamic Polymorphism also known as runtime polymorphism - example is Method Overriding

Q2. Explain Overloading in Java?

Method Overloading is a Compile time polymorphism. In method overloading, method name must be same, but method arguments must be different by number or type or both. In method overloading, return type can be same or different, it doesn’t affect the overloading.

public class Calculator {

	// base-method
	public int add(int a, int b) {
		return a+b;
	}
	
	// throw compile time error - duplicate method
	// we can not overload base-method by just changing return type
	public long add(int a, int b) {
		return a+b;
	}
	
	// overloaded method - number of arguments (3) are different than base-method (2)
	public int add(int a, int b, int c) {
		return a+b+c;
	}
	
	// overloaded method - argument types are different than base-method
	public String add(String a, String b) {
		return a+b;
	}
}

Q3. Explain Overriding in Java?

Method Overriding is a Run time polymorphism. In method overriding, derived (child) class provides the specific implementation of the method that is already provided by the base (parent) class. In method overriding, method signature must be same i.e. method name, arguments and return type.

package com.example.core.oops;

public class Overiding {
	public static void main(String[] args) {
		Animal animal = new Animal();
		animal.makeSound();
		// prints "Animal making sound"

		Animal dog = new Dog();
		dog.makeSound();
		// prints "Bow Bow"

		Animal cat = new Cat();
		cat.makeSound();
		// prints "Meow Meow"
	}
}

class Animal {
	public void makeSound() {
		System.out.println("Animal making sound");
	}
}

class Dog extends Animal {
	public void makeSound() {
		System.out.println("Bow Bow");
	}
}

class Cat extends Animal {
	public void makeSound() {
		System.out.println("Meow Meow");
	}
}

Q4. Can you Override a static method and private method ?

  • No, you cannot override static method since static method is associated with a class whereas overriding is an object instance feature.
  • No, you cannot override private method since private method is not visible outside of a class.

Q5. What is multiple Inheritance? Is it supported by Java?

If a child class inherits the property from multiple classes is known as multiple inheritance. Java does not allow to extend multiple classes.

The problem with multiple inheritance is that if multiple parent classes have the same method name, then at runtime it becomes difficult for the compiler to decide which method to execute from the child class.

Therefore, Java doesn’t support multiple inheritance. The problem is commonly referred to as Diamond Problem.

Java Basics

Java Basics interview questions are very frequently asked from freshers.

Q1. Explain each keyword in main method i.e. public static void main(String[] args).

public class MyClass {
  public static void main(String[] args) {}
}
  • public method have public access and can be executed from outside the class. It has to be public so that java runtime can execute this method.
  • static associates the method with class rather than object. This helps JVM to call main method without class instantiation.
  • void is a return type of main method which returns nothing
  • main is name of java main method and it is fixed. When you execute a class fine, it looks for main method.
  • String[] args is used to pass Java command line arguments and is an array of type String

Q2. What is final keyword in Java?

The final keyword is used as non-access modifier in Java. A final keyword can be used in different contexts such as:

  • Value of final variable cannot be changed once assigned.

  • A final method cannot be overridden by inheriting child classes in Java.

  • A final class cannot be extended by other classes in Java.

    /** final class cannot be extended */
    final class A {
    
      /** final variable value cannot be changed */
      private final var;
    
      /** final method cannot be overridden */
      public void final method() {}
    }
    

Q3. Difference between final, finally and finalize?

  • final is used to apply restrictions on class, methods and variables. final class can’t be inherited, final method can’t be overridden and final variable value can’t be changed once assigned.
  • finally is used along with try and catch block for exception handling. finally block is always executed whether an exception is handled or not. finally block is generally used to clean up the resources such as closing the IO streams and connections.
  • finalize is an Object’s class protected method which is called by the garbage collector on an object that isn’t referenced anymore and have been selected for garbage collection. The method is called before the object is released from the memory by GC. We cannot control when garbage control happens and should not depend on the finalize() method to perform clean up activities.
    class FinalizeObject {
      @Override
        protected void finalize() throws Throwable {
            System.out.println("Execute finalize method");
            super.finalize();
        }
        public static void main(String[] args) throws Exception {
            FinalizeObject object = new FinalizeObject();
            object = null;
            /** Request JVM to perform garbage collection */
            System.gc();
        }
    }
    

Q4. Explain JDK, JRE and JVM

JDK JRE JVM
It stands for Java Development Kit It stands for Java Runtime Environment It stands for Java Virtual Machine
JDK = JDK + JRE + JVM JRE = JRE + JVM JVM = JVM
It contains JRE, JVM, interpreter/loader(java), compiler(javac), debugger, archiver(jar), document generator(JavaDoc) It contains JVM, Class libraries and other supporting files It is a virtual machine contains ClassLoader, Method Area, Heap, Stack memory
You can compile, document, debug, or archive a Java Program with JDK You can execute a Java Program with only JRE, You don’t need JDK JVM translates the bytecode to native machine code

Q5. Why Java is Platform Independent?

Java is platform independent. Let’s understand this

  • When you write a program in Java (.java file) and compile it using javac. It is converted to ByteCode (.class file).
  • This ByteCode is not something which any machine or OS can understand. You need an interpreter to execute this ByteCode and that interpreter is JVM (Java Virtual Machine) in case of Java.
  • JVM is platform dependent. You need to install platform specific JVM based on Operating System you are using Mac OS X, Windows or Linux.
  • You can execute the same ByteCode (.class file) on any platform’s JVM regardless of its Operating System.

So we can say, JVM is platform dependent but Java is platform independent from its magic ByteCode.

Q6. How many ways to create an Object Instance in Java ?

  • New Keyword
  • Cloning using Object.clone() method
  • Reflection using Class.newInstance() method
  • Reflection using Class.getConstructor().newInstance() method
  • Object Serialization and Deserialization
public class ObjectInstance {

	public static void main(String[] args)
			throws CloneNotSupportedException, InstantiationException, IllegalAccessException, IllegalArgumentException,
			InvocationTargetException, NoSuchMethodException, SecurityException, IOException, ClassNotFoundException {
        
        // New Keyword
		ObjectInstance instance1 = new ObjectInstance();

		// Cloning
		ObjectInstance instance2 = (ObjectInstance) instance1.clone();

		// Reflection
		ObjectInstance instance3 = ObjectInstance.class.newInstance();
		ObjectInstance instance4 = ObjectInstance.class.getConstructor().newInstance();

		// Object Serialization and Deserialization
		serialize(instance1);
		ObjectInstance instance5 = deserialize();

	}

	private static void serialize(ObjectInstance objInstance) throws IOException {
		FileOutputStream f = new FileOutputStream("resources/objectinstance.ser");
		try (ObjectOutputStream outputStream = new ObjectOutputStream(f)) {
			outputStream.writeObject(objInstance);
			outputStream.flush();
		}
	}

	private static ObjectInstance deserialize() throws IOException, ClassNotFoundException {
		FileInputStream f = new FileInputStream("resources/objectinstance.ser");
		try (ObjectInputStream inputStream = new ObjectInputStream(f)) {
			return (ObjectInstance) inputStream.readObject();
		}
	}
}

Q7. What is Marker Interface?

A Marker interface is an empty interface (having no fields and methods). Examples of Marker interface are:-
java.io.Serializable,
java.lang.Cloneable,
java.rmi.Remote,
java.util.RandomAccess etc.

Marker Interface provides runtime information about objects to compiler and JVM. Now annotations are used for the same purpose instead of Marker Interface.

Let’s create our own marker interface Deletable to indicate whether an object can be removed from the database.

public interface Deletable {}

public class Entity implements Deletable {
    // implementation details
}

public class ShapeDao {
 
    // other dao methods
 
    public boolean delete(Object object) {
        if (!(object instanceof Deletable)) {
            return false;
        }
 
        // delete implementation details
        
        return true;
    }
}

Q8. What is Autoboxing and Unboxing in Java?

  • Autoboxing is automatic conversion of primitive type to its object wrapper class such as int to Integer by Java Compiler
    //Autoboxing char to Character
    Character c = 'a'; 
    
    //Autoboxing int to Integer
    List<Integer> list = new ArrayList<>();
    list.add(1);
    
  • Unboxing is automatic conversion of object wrapper class to its primitive type such as Double to Double by Java Compiler
    //Unboxing Double to double
    List<Double> list = new ArrayList<>();
    list.add(3.1416);
    double pi = list.get(0);
    

Q9. Why use Generics?

Generics enables types to be parameterized when defining classes and methods so that we can re-use the same code with different types.

Let’s understand this by creating a generic class Element and methods set and get

public class Element<T> {
  // T stands for "Type"
	private T t;
	
	public void set(T t) {
		this.t = t;
	}
	
	public T get() {
		return t;
	}
}

Now can re-use the same code with different types such as Integer and String as follows:-

Element<Integer> num = new Element<>();
num.set(2);
System.out.println(num.get());


Element<String> str = new Element<>();
str.set("generics");
System.out.println(str.get());

Q10. What are the restrictions on Generics?

  1. Cannot instantiate Generic classes with primitive type
    List<int> num = new List<>(); // compile-time error
    
  2. Cannot create instance of Type parameter
    public static <E> void append(List<E> list) {
      E elem = new E();  // compile-time error
      list.add(elem);
    }
    
  3. Cannot declare parametrized static field in Generic class
    public class List<T> {
      // static field type cannot be parametrized since it belongs to class not class-object of type T
      private static T os;
    }
    
  4. Cannot use casts or instanceof with Generic Class
    public static <E> void rtti(List<E> list) {
        if (list instanceof ArrayList<Integer>) {  // compile-time error
            // ...
        }
    }
    
  5. Cannot create Array of Generic class
    List<Integer>[] arrayOfLists = new List<Integer>[2];  // compile-time error
    
  6. Cannot overload a method using same Generic class with different types
    public class Example {
        public void print(Set<String> strSet) { }
        public void print(Set<Integer> intSet) { }  // compile-time error
    }
    

Java Memory

Q1. What is the difference between Heap and Stack Memory in Java?

Features Stack Heap
Memory Stack memory is used only by one thread of execution. Heap memory is used by all the parts of the application.
Access Stack memory can’t be accessed by other threads. Objects stored in the heap are globally accessible.
Memory Management Follows LIFO manner to free memory. Memory management is based on the generation associated with each object.
Lifetime Exists until the end of execution of the thread. Heap memory lives from the start till the end of application execution.
Usage Stack memory only contains local primitive and reference variables to objects in heap space. Whenever an object is created, it’s always stored in the Heap space.

Q2. What is Java Memory Model?

JVM Memory is having separate space for Heap and Permanent Generation Memory

┌------------------- Heap ------------------┐ ┌-- Non-Heap --┐ 
┌------------- New -----------┐ ┌--- Old ---┐ 
┌―――――――――┬―――――――――┬――――――――――┬―――――――――――――┬―――――――――――――――┐
│  Eden   │    S0   │    S1    │   Tenured   │   Permanent   │ 
└―――――――――┴―――――――――┴――――――――――┴―――――――――――――┴―――――――――――――――┘
Heap Memory
  1. Heap is divided into 2 parts - New (Young) Generation and Old Generation.
  2. Heap space is allocated as per -Xms (Initial Heap Size) when JVM starts up and it can increase upto -Xmx (Max Heap Size)
New (Young) Generation
  1. New Generation includes 3 parts - Eden Space and two Survivor Space (S0, S1)
  2. New Generation space is allocated as per -XX:NewSize when JVM starts up and it can increase upto -XX:MaxNewSize
  3. All newly created objects first live here, and GC’ed if they are unused (most die young)
  4. Minor GC is performed when Eden Space is full
Mark Copy (Minor GC)
            Young Generation
┌―――――――――――――――――――――――――――――――――――――┐
│             Eden Space              │
│――――――――――――――――――┬――――――――――――――――――│
│ Survivor Space 1 │ Survivor Space 2 │
└――――――――――――――――――┴――――――――――――――――――┘

1st Minor GC
1. Keep allocating in Eden space
2. Once full, trigger minor GC
3. Mark all live objects in Eden
4. Copy it over to empty survivor space (S1)
5. Reclaim whole Eden space as empty

2nd Minor GC
1. Keep allocating in Eden space
2. Once full, trigger minor GC
3. Mark all live objects in Eden 
4. Copy it over to empty survivor space (S2)
5. Copy live objects of S1 to S2
6. Reclaim both Eden and S1 as empty

3rd Minor GC
...
5. Copy live objects of S2 to S1
6. Reclaim both Eden and S2 as empty
Old Generation
  1. Object moved here after surviving multiple Minor GC OR If Objects are too big for young generation.
  2. Major GC is performed when Old Generation is full.
Mark Sweep Compact (Major GC)
        Old Generation
┌――――――――――――――――――――――――――――┐ 
│ ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ | | | | | │ 1. trigger major GC (aka full GC), once threshold reached
└――――――――――――――――――――――――――――┘    

┌――――――――――――――――――――――――――――┐ 
│ ☑ | ☑ | | ☑☑ | ☑ | | | | | │ 2. mark all live objects
└――――――――――――――――――――――――――――┘  

┌――――――――――――――――――――――――――――┐ 
│ ▇ | ▇ | | ▇▇ | ▇ | | | | | │ 3. sweep/reclaim all dead objects
└――――――――――――――――――――――――――――┘  

┌――――――――――――――――――――――――――――┐ 
│ ▇▇▇▇▇▇ | | | | | | | | | | │ 4. move all live objects together aka compaction
└――――――――――――――――――――――――――――┘  
Permanent Generation
  1. Perm Gen stores String Constant Pool, Per-Class Structure, field and method data
  2. Perm Gen space is allocated as per -XX:PermSize when JVM starts up and it can increase upto -XX:MaxPermSize

Q3. What are Different Types of Garbage Collectors?

Collector Pros Cons Threads Use-Case
SerialGC Smallest Footprint Slow Use Single Thread for both Minor and Major GC Programs with small memory, or running on shared CPU
ParallelGC High Throughput High STW Pauses Use multiple threads for minor and single thread for major GC Batch applications
ParallelOldGC High Throughput High STW Pauses Use multiple threads for both minor and major GC Batch applications
ConcurrentMarkSweepGC Low STW Pauses (Concurrent Mark) Reduced Throughput Use one or more threads for both minor and major GC General Application
G1GC Region Based, Can set STW Pause threshold, Low Latency, High Throughput High Footprint Use multiple threads Big Applications with large heap

*Footprint:- Amount of memory required by GC algo to run
*STW (Stop the world):- GC doesn’t run with application. When GC is running, all application processes are stopped.

Serial vs Parallel GC

  • Serial and Parallel both cause stop-the-world during GC operation
  • Serial collector uses only one GC thread whereas Parallel collector uses multiple GC threads.
  • Parallel collector provide high throughput due to multiple threads

Parallel vs CMS GC

ConcurrentMarkSweep (CMS) performs following Steps:-

initial mark (STW with multiple GC threads)
concurrent tracing (one or more GC threads runs with application)
remark (STW with multiple GC threads)
concurrent sweep (one or more GC threads runs with application)
  • Parallel collector stop-the-world throughout GC operation means 1 high STW pause.
  • CMS stop-the-world only during initial mark and remark phase, during concurrent mark and sweep phase, CMS threads run along with application’s thread means 2 low STW pauses.

G1GC

Divides the heap space into multiple regions (Eden regions, Survivor regions, Old Regions, and Humongous regions)

  • -XX:G1HeapRegionSize=n sets the size of a G1 region. The value will be a power of two and can range from 1MB to 32MB. The goal is to have around 2048 regions based on the minimum Java heap size.
  • -XX:MaxGCPauseMillis=200 sets a target value for desired maximum pause time. The default value is 200 milliseconds.

Q4. Can you force the JVM to perform garbage collection from a Java program?

You cannot force the JVM to perform garbage collection. you can only suggest or indicate to the JVM to perform garbage collection using System.gc().


Q5. How to do JVM Performance tuning?

  1. Heap and Stack Memory:
    -Xms512m             sets the initial heap size to 512MB
    -Xmx512m             sets the max heap size to 512MB, recommended to same as -Xms
    -Xss                 thread stack size
    -XX:NewSize=128m     new generation size typically set 1/4th the size of heap
    -XX:MaxNewSize=128m  max new generation size, recommended to same as -XX:NewSize
    -XX:NewRatio=2       old to young ratio means the old generation occupies 2/3 of the heap while the young generation occupies 1/3
    -XX:SurvivorRatio=6  eden to survivor ratio) means each survivor occupies 1/8 of young generation while eden occupies 6/8   
    
  2. Permanent Generation Memory
    -XX:PermSize
    -XX:MaxPermSize
    
  3. Garbage Collection
    -XX:+UseSerialGC, 
    -XX:+UseParallelGC (-XX:ParallelGCThreads=<N>), 
    -XX:+UseParallelOldGC, 
    -XX:+UseConcMarkSweepGC (-XX:ParallelCMSThreads=<N>), 
    -XX:+UseG1GC
    

JVM Performance Tuning using Parameters

JVM Performance Tuning using Parameters

*Permanent Generation is replaced by Metaspace from Java 8 onwards


Q6. What are Java Profilers?

Java profilers are used to monitor and debug performance and memory leak issues in development and production environment.

Java VisualVM is a profiling tool which provide a GUI to profile Java applications. It comes bundled with JDK and relies on other standalone tools provided in the JDK, such as JConsole, jstat, jstack, jinfo, and jmap.

Other famous JVM profilers are JProfiler and YourKit.

Some of the features of JVM profilers are:-

  • Can use for debugging both local and remote applications
  • Tracking all the JVM details (CPU Usage, Threads, Memory, ClassLoader)
  • Allow to manually run the Garbage Collection
  • Allow to take Heap Dump and Thread Dump
  • CPU Profiling: Debug method execution with stack strace and time taken by each method in stack trace for any performance issue
  • Memory Profiling: Debug the heap and stack memory usage for any possible memory leak.

The JVM Profilers such as VisualVM, JProfiler, and YourKit requires direct connection to the monitored JVM and slow down the application. That is the reason they are mostly used in development environment and not favorable for production use.

APM (Application Performance Monitoring) tools such as AppDynamics, New Relic, DynaTrace, and Grafana are used in production environment instead. APM tools works as Java Agent Profiler which use Java Instrumentation API to inject code into your application. This provides granular level access of the application without affecting the performance.

Java Errors & Exceptions

Q1. ClassNotFoundException vs NoClassDefFoundError?

ClassNotFoundException NoClassDefFoundError
It is an exception. It is of type java.lang.Exception. It is an error. It is of type java.lang.Error.
It occurs when an application tries to load a class at run time which is not updated in the classpath. It occurs when java runtime system doesn’t find a class definition, which is present at compile time, but missing at run time.
It is thrown by the application itself. It is thrown by the methods like Class.forName(), loadClass() and findSystemClass(). It is thrown by the Java Runtime System.
It occurs when classpath is not updated with required JAR files. It occurs when required class definition is missing at runtime.

Q2. Error vs Exception?

Error Exception
Recovering from Error is not possible. We can recover from exceptions by either using try-catch block or throwing exceptions back to the caller.
All errors in java are unchecked type. Exceptions include both checked as well as unchecked type.
Errors are mostly caused by the environment in which program is running. Program itself is responsible for causing exceptions.
Errors can occur at compile time as well as run time.
Compile Time: Syntax Error, Run Time: Logical Error
All exceptions occurs at runtime but checked exceptions are known to the compiler while unchecked are not.
StackOverflowError, OutOfMemoryError Checked Exceptions: SQLException, IOException
Unchecked Exceptions: ArrayIndexOutOfBoundException, NullPointerException, ArithmeticException.

Java Theory

Q1. S.O.L.I.D. (5 class design principle) in Java?

These 5 design principle are know as SOLID principles:-

  • Single Responsibility Principle - One class should have one and only one responsibility. We should not write thousands lines of code in a single class (a.k.a. God Class), instead we should refactor and layer our classes such as Controllers (API), Services (Business Logic), Repositories (Database Connection) for application development.
  • Open Close Principle - Software entities (Classes and methods) should be open for extension, but closed for modification. We should not change the code of existing class or method to add new functionality, instead we should inherit the Class or overload/override the Method.
  • Liskov Substitution - Child class should be able to substitute Parent class during runtime polymorphism.
  • Interface Segregation - Clients should not be forced to implement unnecessary methods which they will not use
  • Dependency Inversion - Depend on abstractions (interfaces and abstract classes), instead of concrete implementations (classes).

Q2. Does Singleton Pattern Follow S.O.L.I.D. Principle?

Singleton pattern do not follow SOLID principle.

  • Singleton class has additional responsibility of providing single instance along with other responsibility such as e.g. Database connection, Configuration Manager.
  • Singleton class is not open for extension, not inheritable.

  • Association (bidirectional one to one, one to many, many to one or many to many association, represented by line with arrow in UML) for e.g. Teacher and Student. Multiple students can associate with a single teacher and a single student can associate with multiple teachers but there is no ownership between the objects and both have their own lifecycle.
  • Aggregation (Has-a relationship, unidirectional association, parent and child can survive individually, represented by line with diamond in UML) for e.g. Car and Wheel. Car can have multiple wheels but wheel can not belong to multiple cars and if we delete the car, wheel need not to be destroyed and used in another car.
  • Composition (Part-of relationship, unidirectional association, child can not survive without parent, represented by line with filled diamond in UML) for e.g. House and Rooms. House can contain multiple rooms there is no independent life of room and any room can not belongs to two different house if we delete the house room will automatically delete.