- Place the Cursor in Line and press Ctrl + R while Debugging instead of using Breakpoints to get the Control over the line
Ideal Debug Perspective Setup
Options in Debug Perspective
Inspect, Display, Execute, Watch
Ideal Debug Perspective Setup
Options in Debug Perspective
Inspect, Display, Execute, Watch
When you added some file as JAR file and do a Debug then the Debug Stack Trace will try to go through code which doesn’t have source attached to it. In such case we can use step filtering to let debugger know files which needs to be skipped while debugging.
In the below code I try to reach for the Constructor StringUtil.But when I try to do so by pressing F5 it throws ClassNotFoundException since the class need to be loaded first time into JVM
ClassNotFoundException
Now I use Step Filer to Skip Debugger going through classes in JRE by Using StepFilter
Window -> Preferences -> Java|Debug|Step Filtering.
Now I check Java.* to make sure I skips JRE code which does class loading into JVM.
Now when I start Debug again It directly Takes me into StringUtil
We can also add other classes through which we don’t want our debugger to flow its control by Creating your own step filters as below
The whole concept of serialization works on versioning. If you save a class object using one version of the class but attempt to deserialize using a newer or different version of the class deserialization might fail.
When you class structure can change in between you serialize the instance and go again to de-serialize it. Changed structure of class will cause JVM to give exception while de-serializing process.This problem can be solved only by adding a unique serial version id to class. It will prevent the compiler to throw the exception by telling that both classes are same, and will load the available instance variables only.
The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender’s class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named “serialVersionUID” that must be static, final, and of type long
static final long serialVersionUID = 69L;
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification
Singleton.java
public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
In a Multi-threaded Environment
. . . if (instance == null) { //Two threads may have passed the condition and might have got in instance = new Singleton(); } . . .
Now there are many work arounds but DoubleCheckedLocking, Enum Singleton and Initialization On Demand Holder are the Optimized approach
Refer Table in Link
Method 1
In this method we does static block initialization of Singleton along with synchronized getInstance() method which allows the access to only one thread at a point of time.
Singleton.java
public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
But the above method is expensive since there is unnecessary locking and unlocking done every time the object get accessed.
Method 2(Double Checked Locking Singleton)
Instead of synchronizing the whole method lets synchronize the block of code which allows single thread to access the instance during the first time access.The consecutive thread would be served with the same thread allocated for the First thread once it is done with its task.
Singleton.java
public class Singleton { private volatile static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
Other ways of achieving singleton are by using Eager Initialization and ENUM which has its own advantages and disadvantages.
In which scenario we should serialize a singleton?
Imagine you have a long-running app and want to be able to shut it down and later continue at the point where it was shut down (e.g. in order to do hardware maintenance). If the app uses a singleton that is stateful, you’d have to be able to save and restore the sigleton’s state, which is most easily done by serializing it.
Is it possible to serialize a singleton object?
2 Methods
readResolve() method in Singleton Class implementing Serialization
. . // readResolve method to preserve singleton property private Object readResolve() { // Return the one true Elvis and let the garbage collector // take care of the Elvis impersonator. return INSTANCE; } . .
Why you need readResolve() Method
This method will be invoked when you will de-serialize the object. Inside this method, you must return the existing instance to ensure single instance application wide.
The Way serialization works is as below
Serializes the Object Property -> Stores to Persistent Storage
From Persistent Storage -> Creates new Object and Sets Properties of Object
The Object Before Serialization and after Serialization are not same. Only the Object Properties are same
Now lets take a simple Example where we serializes the PrintReport Class which has priority as one of its Object Variable.priority tells which should be given first preference while printing
PrintReport.java
package com.mugil.org; import java.io.Serializable; public class PrintReport implements Serializable { private static PrintReport instance = null; public static PrintReport getInstance() { if (instance == null) { instance = new PrintReport(); } return instance; } private transient int priority = 2; public int getPriority() { return priority; } public void setPriority(int priority) { this.priority = priority; } }
Now when the above singleton which implements serialization gets called as below
PrintMedicalReport.java
package com.mugil.org; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; public class PrintMedicalReport { static PrintReport instanceOne = PrintReport.getInstance(); public static void main(String[] args) { try { // Serialize to a file ObjectOutput out = new ObjectOutputStream(new FileOutputStream( "filename.ser")); out.writeObject(instanceOne); out.close(); instanceOne.setPriority(1); // Serialize to a file ObjectInput in = new ObjectInputStream(new FileInputStream( "filename.ser")); PrintReport instanceTwo = (PrintReport) in.readObject(); in.close(); System.out.println(instanceOne.getPriority()); System.out.println(instanceTwo.getPriority()); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
Output
1 2
Note in the above code the instanceOne.setPriority(2); should have been called before out.writeObject(instanceOne).But that is not the case since the example explains the Object are different before and after Serialization.Only Object Properties(Metadata) are stored during serialization not the actual object.
You can see the Class Prints default Priority value in the output.
Now in context to singleton we want to maintain exactly one Object exist before and after serialization. Not with two object with same set of attributes.To achieve this we add readResolve() Method.
PrintReport.java
package com.mugil.org; import java.io.Serializable; public class PrintReport implements Serializable { private volatile static PrintReport instance = null; public static PrintReport getInstance() { if (instance == null) { instance = new PrintReport(); } return instance; } private int priority = 1; public int getPriority() { return priority; } public void setPriority(int priority) { this.priority = priority; } protected Object readResolve() { return instance; } }
Now when the PrintMedicalReport class gets executed the Output would be as below
Output
1 1
When you Serialize and Deserialize new file would be created and stored in disk every time.
In the above image by changing the filename.ser text you can change the attribute of objects serialized. This is known as Serialization attack. To overcome this you must declare all instance fields as transient.
Lets Consider the below Singleton code which uses Double Checked Locking
DoubleCheckLocking.java
public class DoubleCheckLocking { public static class SearchBox { private static volatile SearchBox searchBox; //Private constructor private SearchBox() {} //Static method to get instance public static SearchBox getInstance() { if (searchBox == null) { // first time lock synchronized (SearchBox.class) { if (searchBox == null) { // second time lock searchBox = new SearchBox(); } } } return searchBox; } }
Lets dive deep into the code where Double Checking actually takes place
if (searchBox == null) { // first time lock synchronized (SearchBox.class) { if (searchBox == null) { // second time lock searchBox = new SearchBox(); } } }